package com.ecep.contract.cloud.u8.ctx;

import static com.ecep.contract.SpringApp.getBean;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.data.domain.Sort;

import com.ecep.contract.MessageHolder;
import com.ecep.contract.constant.CloudServiceConstant;
import com.ecep.contract.ds.contract.service.SaleOrdersService;
import com.ecep.contract.ds.contract.service.SalesOrderItemService;
import com.ecep.contract.model.Contract;
import com.ecep.contract.model.SalesOrder;
import com.ecep.contract.model.SalesOrderItem;
import com.ecep.contract.util.NumberUtils;

import lombok.Setter;

public class SalesOrderCtx extends AbstractYongYouU8Ctx {

    @Setter
    private SaleOrdersService saleOrdersService;
    @Setter
    private SalesOrderItemService orderItemService;

    SaleOrdersService getSaleOrdersService() {
        if (saleOrdersService == null) {
            saleOrdersService = getBean(SaleOrdersService.class);
        }
        return saleOrdersService;
    }

    SalesOrderItemService getOrderItemService() {
        if (orderItemService == null) {
            orderItemService = getBean(SalesOrderItemService.class);
        }
        return orderItemService;
    }


    public List<SalesOrder> syncByContract(Contract contract, MessageHolder holder) {
        SaleOrdersService saleOrdersService = getSaleOrdersService();
        SalesOrderItemService orderItemService = getOrderItemService();

        List<SalesOrder> orders = saleOrdersService.findAll((root, q, cb) -> {
            return cb.equal(root.get("contract"), contract);
        }, Sort.unsorted());
        holder.debug("查找到 " + orders.size() + " 条销售订单记录在数据库中");
        Map<String, SalesOrder> ordersMap = orders.stream().collect(Collectors.toMap(SalesOrder::getCode, item -> item));

        List<SalesOrderItem> items = orderItemService.findAll((root, q, cb) -> {
            return cb.equal(root.get("order").get("contract"), contract);
        }, Sort.unsorted());

        // 按 order 分组
        Map<SalesOrder, Map<String, SalesOrderItem>> itemMap = items.stream().collect(Collectors.groupingBy(SalesOrderItem::getOrder,
                Collectors.toMap(SalesOrderItem::getCode, item -> item)));

        // 查询 U8 数据库
        List<Map<String, Object>> ds = repository.findAllSalesOrderItemByContractCode(contract.getCode());
        holder.debug("查找到 " + ds.size() + " 条销售订单条目记录在 " + CloudServiceConstant.U8_NAME);

        Map<SalesOrder, List<SalesOrderItem>> updateMap = new HashMap<>();
        for (Map<String, Object> map : ds) {
            String orderCode = Optional.ofNullable(map.get("cSOCode")).map(Object::toString).orElse("");
            if (orderCode.isEmpty()) {
                holder.warn("跳过无效销售订单记录：缺少 cSOCode");
                continue;
            }
            SalesOrder order = ordersMap.get(orderCode);
            if (order == null) {
                order = new SalesOrder();
                order.setContract(contract);
                order.setCode(orderCode);

                order = saleOrdersService.save(order);
                ordersMap.put(orderCode, order);
                holder.info("新增销售订单 #" + orderCode);
            }
        }
        for (Map<String, Object> map : ds) {
            // holder.debug("条目：" + map.toString());
            String orderCode = Optional.ofNullable(map.get("cSOCode")).map(Object::toString).orElse("");
            if (orderCode.isEmpty()) {
                holder.warn("跳过无效销售订单记录：缺少 cSOCode");
                continue;
            }
            SalesOrder order = ordersMap.get(orderCode);

            boolean itemModified = false;
            List<SalesOrderItem> updates = updateMap.computeIfAbsent(order, k -> new ArrayList<>());

            // 获取条目标识并处理 null
            String refId = Optional.ofNullable(map.get("iSOsID")).map(Object::toString).orElse("");
            if (refId.isEmpty()) {
                holder.warn("跳过条目：订单 " + orderCode + " 缺少 iSOsID");
                continue;
            }
            Map<String, SalesOrderItem> subItemMap = itemMap.get(order);
            SalesOrderItem item = null;
            if (subItemMap != null) {
                item = subItemMap.remove(refId);
            }

            if (item == null) {
                item = new SalesOrderItem();
                item.setOrder(order);
                item.setCode(refId);
                itemModified = true;

                holder.info("新增销售订单条目 #" + refId);
            }
            MessageHolder subHolder = holder.sub("---| ");
            if (applySaleOrderItemDetail(item, map, subHolder)) {
                itemModified = true;
            }
            if (itemModified) {
                item = orderItemService.save(item);
            }
            updates.add(item);
        }

        for (SalesOrder order : updateMap.keySet()) {
            holder.debug("销售订单 #" + order.getCode());
            if (applySalesOrderDetail(order, repository.querySalesOrderDetail(order.getCode()), holder)) {
                saleOrdersService.save(order);
            }
        }

        if (!itemMap.isEmpty()) {
            for (Map<String, SalesOrderItem> subMap : itemMap.values()) {
                if (!subMap.isEmpty()) {
                    for (SalesOrderItem item : subMap.values()) {
                        holder.info("删除销售订单条目");
                        orderItemService.delete(item);
                    }
                }
            }

            for (SalesOrder order : updateMap.keySet()) {
                itemMap.remove(order);
            }
            if (!itemMap.isEmpty()) {
                holder.info("剩余 " + itemMap.size() + " 个销售订单条目");
            }
        }

        return new ArrayList<>(updateMap.keySet());

    }

    private boolean applySalesOrderDetail(SalesOrder order, Map<String, Object> map, MessageHolder holder) {
        String code = (String) map.get("cSOCode");

        String cCloser = (String) map.get("cCloser");

        String memo = (String) map.get("cMemo");

        boolean modified = false;

        if (!Objects.equals(order.getCode(), code)) {
            order.setCode(code);
            holder.info("订单编号更新为 " + code);
            modified = true;
        }

        if (updateEmployeeByCode(order::getEmployee, order::setEmployee, (String) map.get("cPersonCode"), holder, "业务员")) {
            modified = true;
        }
        if (updateEmployeeByName(order::getMaker, order::setMaker, (String) map.get("cMaker"), holder, "制单人")) {
            modified = true;
        }
        if (updateEmployeeByName(order::getVerifier, order::setVerifier, (String) map.get("cVerifier"), holder, "审核人")) {
            modified = true;
        }

        if (updateLocalDate(order::getMakerDate, order::setMakerDate, (Timestamp) map.get("dcreatesystime"), holder, "制单日期")) {
            modified = true;
        }
        if (updateLocalDate(order::getVerifierDate, order::setVerifierDate, (Timestamp) map.get("dverifysystime"), holder, "审核日期")) {
            modified = true;
        }

        if (!Objects.equals(order.getDescription(), memo)) {
            order.setDescription(memo);
            holder.info("描述修改为: " + memo);
            modified = true;
        }

        return modified;
    }


    private boolean applySaleOrderItemDetail(SalesOrderItem item, Map<String, Object> map, MessageHolder holder) {
        String code = String.valueOf(map.get("iSOsID"));
        String spec = (String) map.get("cInvName");
        String title = (String) map.get("cInvName");
        double quantity = (double) map.get("iQuantity");
        double taxRate = (double) map.get("iTaxRate");
        double taxPrice = (double) map.get("iTaxUnitPrice");
        double exclusiveTaxPrice = (double) map.get("iUnitPrice");
        BigDecimal amount = (BigDecimal) map.get("iSum");

        String memo = (String) map.get("cMemo");

        boolean modified = false;

        holder.debug("条目：" + title + " x " + amount);


        if (!Objects.equals(item.getCode(), code)) {
            item.setCode(code);
            holder.info("代码修改为: " + code);
            modified = true;
        }
        if (!Objects.equals(item.getName(), title)) {
            item.setName(title);
            holder.info("名称修改为: " + title);
            modified = true;
        }
        if (!NumberUtils.equals(item.getExclusiveTaxPrice(), exclusiveTaxPrice)) {
            item.setExclusiveTaxPrice(exclusiveTaxPrice);
            holder.info("不含税单价修改为: " + exclusiveTaxPrice);
            modified = true;
        }
        if (!NumberUtils.equals(item.getPrice(), taxPrice)) {
            item.setPrice(taxPrice);
            holder.info("含税单价修改为: " + taxPrice);
            modified = true;
        }
        if (!NumberUtils.equals(item.getTaxRate(), taxRate)) {
            item.setTaxRate(taxRate);
            holder.info("税率修改为: " + taxRate);
            modified = true;
        }
        if (!NumberUtils.equals(item.getQuantity(), quantity)) {
            item.setQuantity(quantity);
            holder.info("数量修改为: " + quantity);
            modified = true;
        }
        if (updateLocalDate(item::getStartDate, item::setStartDate, (Timestamp) map.get("dPreDate"), holder, "开始日期")) {
            modified = true;
        }
        if (updateLocalDate(item::getEndDate, item::setEndDate, (Timestamp) map.get("dPreMoDate"), holder, "结束日期")) {
            modified = true;
        }

        if (!Objects.equals(item.getDescription(), memo)) {
            item.setDescription(memo);
            modified = true;
        }

        return modified;
    }
}
