package com.zt.plat.module.base.service.plandate;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.module.base.controller.admin.plandate.vo.PlanDatePageReqVO;
import com.zt.plat.module.base.controller.admin.plandate.vo.PlanDateRespVO;
import com.zt.plat.module.base.controller.admin.plandate.vo.RealTimeReportsTreeRespVO;
import com.zt.plat.module.contractorder.api.dto.order.OrderDTO;
import com.zt.plat.module.receivedeliver.api.bill.BillMainApi;
import com.zt.plat.module.receivedeliver.api.bill.dto.billMain.BillMainExecutionVolumeReqDTO;
import com.zt.plat.module.receivedeliver.api.bill.dto.billMain.BillMainExecutionVolumeStatisticsRespDTO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Validated
public class RealTimeReportsServiceImpl implements RealTimeReportsService {

    @Resource
    private PlanDateService planDateService;
    @Resource
    private PlanOrderService planOrderService;
    @Resource
    private BillMainApi billMainApi;

    @Override
    public List<RealTimeReportsTreeRespVO> tree(PlanDatePageReqVO reqVO) {
        // 1. 获取计划数据树形结构
        List<PlanDateRespVO> planDateTree = planDateService.listPlanDateTree(reqVO);
        if (planDateTree == null || planDateTree.isEmpty()) {
            return new ArrayList<>();
        }

        // 2. 获取执行量数据
//        List<BillMainExecutionVolumeStatisticsRespDTO> executionVolumeList = getExecutionVolumeData(reqVO);
        // 构建执行量数据映射（物料编码为KEY，兼容多客商/多订单的情况，取第一条匹配数据）
    //    Map<String, BillMainExecutionVolumeStatisticsRespDTO> executionVolumeMap = buildExecutionVolumeMap(executionVolumeList);

        // 3. 转换为树形VO并填充执行量
        List<RealTimeReportsTreeRespVO> resultTree = convertPlanDateToTreeVO(planDateTree, reqVO);

        // 4. 后序遍历汇总子节点执行量（父节点=所有子节点执行量之和）
        traverseAndSumExecutionVolume(resultTree);

        return resultTree;
    }

    /**
     * 调用API获取执行量数据
     */
    private List<BillMainExecutionVolumeStatisticsRespDTO> getExecutionVolumeData(PlanDatePageReqVO reqVO, PlanDateRespVO planDate) {
        //获取已绑定的订单
        PageResult<OrderDTO> boundOrder = planOrderService.getBoundOrder(String.valueOf(planDate.getId()));
        if (boundOrder == null || boundOrder.getList() == null || boundOrder.getList().isEmpty()) {
            return new ArrayList<>();
        }
        BillMainExecutionVolumeReqDTO reqDTO = new BillMainExecutionVolumeReqDTO();
        reqDTO.setQueryYear(reqVO.getYear());
        reqDTO.setOrderNos(boundOrder.getList().stream().map(OrderDTO::getSystemOrderNumber).collect(Collectors.toList()));
        CommonResult<List<BillMainExecutionVolumeStatisticsRespDTO>> result = billMainApi.getBillMainExecutionVolumeList(reqDTO);
        return result != null && result.getData() != null ? result.getData() : new ArrayList<>();
    }

    /**
     * 构建执行量数据映射（按物料编码匹配，唯一标识）
     * 注：如果同一物料编码有多个DTO，取第一条（可根据业务调整为求和/取最新）
     */
    private Map<String, BillMainExecutionVolumeStatisticsRespDTO> buildExecutionVolumeMap(
            List<BillMainExecutionVolumeStatisticsRespDTO> executionVolumeList) {
        Map<String, BillMainExecutionVolumeStatisticsRespDTO> map = new HashMap<>();
        for (BillMainExecutionVolumeStatisticsRespDTO dto : executionVolumeList) {
            // 核心匹配键：物料编码（优先）→ 物料名称
            String key = Optional.ofNullable(dto.getMaterialCoding()).orElse(dto.getMaterialName());
            if (key != null && !map.containsKey(key)) { // 避免覆盖，只存第一条
                map.put(key, dto);
            }
        }
        return map;
    }

    /**
     * 将PlanDateRespVO树形转换为RealTimeReportsTreeRespVO，并填充执行量
     */
    private List<RealTimeReportsTreeRespVO> convertPlanDateToTreeVO(
            List<PlanDateRespVO> planDateList,
            PlanDatePageReqVO reqVO) {
        List<RealTimeReportsTreeRespVO> treeVOList = new ArrayList<>();
        for (PlanDateRespVO planDate : planDateList) {
            List<BillMainExecutionVolumeStatisticsRespDTO> executionVolumeData = getExecutionVolumeData(reqVO, planDate);
            Map<String, BillMainExecutionVolumeStatisticsRespDTO> executionVolumeMap = buildExecutionVolumeMap(executionVolumeData);
            RealTimeReportsTreeRespVO treeVO = convertSingleNode(planDate, executionVolumeMap);
            // 递归转换子节点
            if (planDate.getChildren() != null && !planDate.getChildren().isEmpty()) {
                treeVO.setChildren(convertPlanDateToTreeVO(planDate.getChildren(), reqVO));
                treeVO.setIsLeaf(false);
            } else {
                treeVO.setChildren(new ArrayList<>());
                treeVO.setIsLeaf(true);
            }
            treeVOList.add(treeVO);
        }
        return treeVOList;
    }

    /**
     * 转换单个节点并填充执行量（核心：对齐DTO字段）
     */
    private RealTimeReportsTreeRespVO convertSingleNode(
            PlanDateRespVO planDate,
            Map<String, BillMainExecutionVolumeStatisticsRespDTO> executionVolumeMap) {
        RealTimeReportsTreeRespVO treeVO = new RealTimeReportsTreeRespVO();

        // 1. 复制基础字段
        treeVO.setId(planDate.getId());
        treeVO.setPlanName(planDate.getPlanName());
        treeVO.setPlanCoding(planDate.getPlanCoding());
        treeVO.setParentId(planDate.getParentId());
        treeVO.setYear(planDate.getYear());
        treeVO.setInitialValue(planDate.getInitialValue());
        treeVO.setAverageValue(planDate.getAverageValue());
        treeVO.setSumValue(planDate.getSumValue());
        treeVO.setCreateTime(planDate.getCreateTime());

        // 2. 复制12个月计划值
        treeVO.setJanuary(planDate.getJanuary());
        treeVO.setFebruary(planDate.getFebruary());
        treeVO.setMarch(planDate.getMarch());
        treeVO.setApril(planDate.getApril());
        treeVO.setMay(planDate.getMay());
        treeVO.setJune(planDate.getJune());
        treeVO.setJuly(planDate.getJuly());
        treeVO.setAugust(planDate.getAugust());
        treeVO.setSeptember(planDate.getSeptember());
        treeVO.setOctober(planDate.getOctober());
        treeVO.setNovember(planDate.getNovember());
        treeVO.setDecember(planDate.getDecember());

        // 3. 填充12个月执行量（核心：严格对齐DTO字段）
        fillExecutionVolume(treeVO, planDate, executionVolumeMap);

        // 4. 初始化层级
        treeVO.setLevel(0);

        return treeVO;
    }

    /**
     * 为节点填充执行量数据（适配DTO的实际字段名）
     */
    private void fillExecutionVolume(
            RealTimeReportsTreeRespVO treeVO,
            PlanDateRespVO planDate,
            Map<String, BillMainExecutionVolumeStatisticsRespDTO> executionVolumeMap) {
        // 匹配规则：计划编码/计划名称 → 物料编码/物料名称（根据实际业务调整匹配逻辑）
        String matchKey;
        // 优先用计划编码匹配物料编码
        if (planDate.getPlanCoding() != null) {
            matchKey = planDate.getPlanCoding();
        }
        // 备用：计划名称匹配物料名称
        else if (planDate.getPlanName() != null) {
            matchKey = planDate.getPlanName();
        } else {
            matchKey = null;
        }

        BillMainExecutionVolumeStatisticsRespDTO executionDTO = null;
        if (matchKey != null) {
            executionDTO = executionVolumeMap.get(matchKey);
            // 备用匹配：如果物料名称包含计划名称（模糊匹配，可选）
            if (executionDTO == null) {
                executionDTO = executionVolumeMap.entrySet().stream()
                        .filter(entry -> entry.getKey().contains(matchKey))
                        .map(Map.Entry::getValue)
                        .findFirst()
                        .orElse(null);
            }
        }

        if (executionDTO == null) {
            // 无匹配执行量，设为0
            setZeroToAllExecutionFields(treeVO);
            return;
        }

        // ========== 严格对齐DTO的12个月执行量字段 ==========
        treeVO.setJanuaryExecute(getBigDecimalValue(executionDTO.getJanExecutionQuantity()));
        treeVO.setFebruaryExecute(getBigDecimalValue(executionDTO.getFebExecutionQuantity()));
        treeVO.setMarchExecute(getBigDecimalValue(executionDTO.getMarExecutionQuantity()));
        treeVO.setAprilExecute(getBigDecimalValue(executionDTO.getAprExecutionQuantity()));
        treeVO.setMayExecute(getBigDecimalValue(executionDTO.getMayExecutionQuantity()));
        treeVO.setJuneExecute(getBigDecimalValue(executionDTO.getJunExecutionQuantity()));
        treeVO.setJulyExecute(getBigDecimalValue(executionDTO.getJulExecutionQuantity()));
        treeVO.setAugustExecute(getBigDecimalValue(executionDTO.getAugExecutionQuantity()));
        treeVO.setSeptemberExecute(getBigDecimalValue(executionDTO.getSepExecutionQuantity()));
        treeVO.setOctoberExecute(getBigDecimalValue(executionDTO.getOctExecutionQuantity()));
        treeVO.setNovemberExecute(getBigDecimalValue(executionDTO.getNovExecutionQuantity()));
        treeVO.setDecemberExecute(getBigDecimalValue(executionDTO.getDecExecutionQuantity()));

        // 自动计算合计执行量和执行率
        treeVO.calculateSumExecuteValue();
        treeVO.calculateExecuteRate();
    }

    /**
     * 后序遍历树形VO，汇总子节点执行量到父节点
     */
    private void traverseAndSumExecutionVolume(List<RealTimeReportsTreeRespVO> rootNodeList) {
        if (rootNodeList == null || rootNodeList.isEmpty()) {
            return;
        }
        for (RealTimeReportsTreeRespVO rootNode : rootNodeList) {
            traverseNodeAndSum(rootNode, 0);
        }
    }

    /**
     * 递归遍历单个节点并汇总子节点执行量
     */
    private void traverseNodeAndSum(RealTimeReportsTreeRespVO currentNode, int level) {
        currentNode.setLevel(level); // 设置节点层级

        // 1. 先递归处理子节点
        List<RealTimeReportsTreeRespVO> children = currentNode.getChildren();
        if (children != null && !children.isEmpty()) {
            for (RealTimeReportsTreeRespVO child : children) {
                traverseNodeAndSum(child, level + 1);
            }

            // 2. 汇总子节点执行量到当前节点（如果当前节点无直接执行量）
            BigDecimal sumChildExecute = children.stream()
                    .map(RealTimeReportsTreeRespVO::getSumExecuteValue)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 如果父节点本身无执行量，用子节点总和填充
            if (currentNode.getSumExecuteValue() == null || currentNode.getSumExecuteValue().compareTo(BigDecimal.ZERO) == 0) {
                currentNode.setSumExecuteValue(sumChildExecute);
                // 重新计算执行率
                currentNode.calculateExecuteRate();
            }
        }
    }

    // ========== 工具方法 ==========
    /**
     * 空值转换为BigDecimal.ZERO
     */
    private BigDecimal getBigDecimalValue(BigDecimal value) {
        return value == null ? BigDecimal.ZERO : value;
    }

    /**
     * 所有执行量字段设为0
     */
    private void setZeroToAllExecutionFields(RealTimeReportsTreeRespVO treeVO) {
        treeVO.setJanuaryExecute(BigDecimal.ZERO);
        treeVO.setFebruaryExecute(BigDecimal.ZERO);
        treeVO.setMarchExecute(BigDecimal.ZERO);
        treeVO.setAprilExecute(BigDecimal.ZERO);
        treeVO.setMayExecute(BigDecimal.ZERO);
        treeVO.setJuneExecute(BigDecimal.ZERO);
        treeVO.setJulyExecute(BigDecimal.ZERO);
        treeVO.setAugustExecute(BigDecimal.ZERO);
        treeVO.setSeptemberExecute(BigDecimal.ZERO);
        treeVO.setOctoberExecute(BigDecimal.ZERO);
        treeVO.setNovemberExecute(BigDecimal.ZERO);
        treeVO.setDecemberExecute(BigDecimal.ZERO);
        // 计算合计和执行率
        treeVO.calculateSumExecuteValue();
        treeVO.calculateExecuteRate();
    }

    // ========== 调试用遍历方法（保留） ==========
    public static void traversePlanDateTreePostOrder(List<PlanDateRespVO> rootNodeList) {
        if (rootNodeList == null || rootNodeList.isEmpty()) {
            System.out.println("入参planDate为空，无需遍历");
            return;
        }
        for (PlanDateRespVO rootNode : rootNodeList) {
            traverseNodePostOrder(rootNode, 0);
        }
    }

    private static void traverseNodePostOrder(PlanDateRespVO currentNode, int level) {
        List<PlanDateRespVO> children = currentNode.getChildren();
        if (children != null && !children.isEmpty()) {
            for (PlanDateRespVO child : children) {
                traverseNodePostOrder(child, level + 1);
            }
        }
        handleCurrentNode(currentNode, level);
    }

    private static void handleCurrentNode(PlanDateRespVO node, int level) {
        String indent = "  ".repeat(level);
        System.out.printf("%s【层级%d】计划名称：%s，计划编码：%s，合计值：%s%n",
                indent, level, node.getPlanName(), node.getPlanCoding(), node.getSumValue());
    }
}