package com.yhy.module.core.service.workbench.impl;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.yhy.module.core.controller.admin.workbench.vo.WbBoqDivisionRespVO;
import com.yhy.module.core.controller.admin.workbench.vo.progresspayment.PeriodInfoVO;
import com.yhy.module.core.controller.admin.workbench.vo.progresspayment.ProgressDivisionSimpleVO;
import com.yhy.module.core.controller.admin.workbench.vo.progresspayment.ProgressDivisionTreeRespVO;
import com.yhy.module.core.controller.admin.workbench.vo.progresspayment.ProgressPaymentModeRespVO;
import com.yhy.module.core.controller.admin.workbench.vo.progresspayment.ProgressPaymentModeWithDivisionsRespVO;
import com.yhy.module.core.dal.dataobject.workbench.ProgressDivisionDO;
import com.yhy.module.core.dal.dataobject.workbench.ProgressPaymentModeDO;
import com.yhy.module.core.dal.mysql.workbench.ProgressDivisionMapper;
import com.yhy.module.core.service.workbench.ProgressDivisionService;
import com.yhy.module.core.service.workbench.ProgressPaymentModeService;
import com.yhy.module.core.service.workbench.WbBoqDivisionService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 进度款-清单关联 Service 实现类
 *
 * @author yhy
 */
@Service
public class ProgressDivisionServiceImpl implements ProgressDivisionService {

    @Resource
    private ProgressDivisionMapper progressDivisionMapper;

    @Resource
    private WbBoqDivisionService wbBoqDivisionService;

    @Resource
    private ProgressPaymentModeService progressPaymentModeService;

    @Resource
    private com.yhy.module.core.dal.mysql.workbench.ProgressPaymentModeMapper progressPaymentModeMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveOrUpdate(Long progressPaymentModeId, Long boqDivisionId, BigDecimal periodValue) {
        // 查询是否已存在
        ProgressDivisionDO existDO = progressDivisionMapper.selectByPaymentModeIdAndBoqDivisionId(
                progressPaymentModeId, boqDivisionId);
        
        if (existDO != null) {
            // 更新
            ProgressDivisionDO updateDO = new ProgressDivisionDO();
            updateDO.setId(existDO.getId());
            updateDO.setPeriodValue(periodValue);
            progressDivisionMapper.updateById(updateDO);
            return existDO.getId();
        } else {
            // 创建
            ProgressDivisionDO newDO = ProgressDivisionDO.builder()
                    .progressPaymentModeId(progressPaymentModeId)
                    .boqDivisionId(boqDivisionId)
                    .periodValue(periodValue)
                    .build();
            progressDivisionMapper.insert(newDO);
            return newDO.getId();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchSaveOrUpdate(Long progressPaymentModeId, Map<Long, BigDecimal> periodValueMap) {
        if (periodValueMap == null || periodValueMap.isEmpty()) {
            return;
        }
        
        // 查询已存在的记录
        List<ProgressDivisionDO> existList = progressDivisionMapper.selectListByProgressPaymentModeId(progressPaymentModeId);
        Map<Long, ProgressDivisionDO> existMap = new HashMap<>();
        for (ProgressDivisionDO item : existList) {
            existMap.put(item.getBoqDivisionId(), item);
        }
        
        // 遍历处理
        for (Map.Entry<Long, BigDecimal> entry : periodValueMap.entrySet()) {
            Long boqDivisionId = entry.getKey();
            BigDecimal periodValue = entry.getValue();
            
            ProgressDivisionDO existDO = existMap.get(boqDivisionId);
            if (existDO != null) {
                // 更新（只更新有变化的）
                if (!periodValue.equals(existDO.getPeriodValue())) {
                    ProgressDivisionDO updateDO = new ProgressDivisionDO();
                    updateDO.setId(existDO.getId());
                    updateDO.setPeriodValue(periodValue);
                    progressDivisionMapper.updateById(updateDO);
                }
            } else {
                // 创建
                ProgressDivisionDO newDO = ProgressDivisionDO.builder()
                        .progressPaymentModeId(progressPaymentModeId)
                        .boqDivisionId(boqDivisionId)
                        .periodValue(periodValue)
                        .build();
                progressDivisionMapper.insert(newDO);
            }
        }
    }

    @Override
    public List<ProgressDivisionDO> getListByProgressPaymentModeId(Long progressPaymentModeId) {
        return progressDivisionMapper.selectListByProgressPaymentModeId(progressPaymentModeId);
    }

    @Override
    public Map<Long, BigDecimal> getPeriodValueMap(Long progressPaymentModeId) {
        List<ProgressDivisionDO> list = getListByProgressPaymentModeId(progressPaymentModeId);
        Map<Long, BigDecimal> map = new HashMap<>();
        for (ProgressDivisionDO item : list) {
            map.put(item.getBoqDivisionId(), item.getPeriodValue());
        }
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByProgressPaymentModeId(Long progressPaymentModeId) {
        progressDivisionMapper.deleteByProgressPaymentModeId(progressPaymentModeId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteByBoqDivisionId(Long boqDivisionId) {
        progressDivisionMapper.delete(new LambdaQueryWrapperX<ProgressDivisionDO>()
                .eq(ProgressDivisionDO::getBoqDivisionId, boqDivisionId));
    }

    @Override
    public List<ProgressDivisionTreeRespVO> getTreeWithPeriodInfo(Long compileTreeId, Long progressPaymentModeId) {
        // 1. 获取分部分项树（含定额单价计算）
        List<WbBoqDivisionRespVO> tree = wbBoqDivisionService.getTreeWithPrice(compileTreeId);
        
        // 2. 获取进度款模式信息
        ProgressPaymentModeDO paymentMode = null;
        if (progressPaymentModeId != null) {
            paymentMode = progressPaymentModeMapper.selectById(progressPaymentModeId);
        }
        
        // 3. 查询进度款-清单关联数据，构建 Map
        Map<Long, BigDecimal> periodValueMap = new HashMap<>();
        if (progressPaymentModeId != null) {
            periodValueMap = getPeriodValueMap(progressPaymentModeId);
        }
        
        // 4. 转换树并绑定期数信息
        return convertTreeWithPeriodInfo(tree, paymentMode, periodValueMap);
    }

    /**
     * 转换树结构并绑定期数信息
     * 只对 nodeType='boq' 的清单节点进行绑定
     */
    private List<ProgressDivisionTreeRespVO> convertTreeWithPeriodInfo(
            List<WbBoqDivisionRespVO> sourceTree,
            ProgressPaymentModeDO paymentMode,
            Map<Long, BigDecimal> periodValueMap) {
        
        if (CollUtil.isEmpty(sourceTree)) {
            return new ArrayList<>();
        }
        
        List<ProgressDivisionTreeRespVO> result = new ArrayList<>();
        
        for (WbBoqDivisionRespVO source : sourceTree) {
            ProgressDivisionTreeRespVO target = new ProgressDivisionTreeRespVO();
            BeanUtils.copyProperties(source, target);
            
            // 只对清单节点绑定期数信息
            if ("boq".equals(source.getNodeType()) && paymentMode != null) {
                BigDecimal periodValue = periodValueMap.get(source.getId());
//                if (periodValue != null) {
                    PeriodInfoVO periodInfo = new PeriodInfoVO();
                    periodInfo.setProgressPaymentModeId(paymentMode.getId());
                    periodInfo.setPeriodValue(periodValue);
                    periodInfo.setPeriodNumber(paymentMode.getPeriodNumber());
                    periodInfo.setProgressPaymentModeName(paymentMode.getName());
                    target.setPeriod(periodInfo);
//                }
            }
            
            // 递归处理子节点
            if (CollUtil.isNotEmpty(source.getChildren())) {
                // 由于泛型类型限制，需要强制转换（运行时安全，因为 ProgressDivisionTreeRespVO 继承 WbBoqDivisionRespVO）
                @SuppressWarnings("unchecked")
                List<WbBoqDivisionRespVO> children = (List<WbBoqDivisionRespVO>) (List<?>) 
                        convertTreeWithPeriodInfo(source.getChildren(), paymentMode, periodValueMap);
                target.setChildren(children);
            }
            
            result.add(target);
        }
        
        return result;
    }

    @Override
    public List<ProgressPaymentModeWithDivisionsRespVO> getProgressPaymentModeWithDivisionsList(Long projectId) {
        // 1. 查询项目下的所有进度款模式
        List<ProgressPaymentModeRespVO> modeList = progressPaymentModeService.getProgressPaymentModeList(projectId);
        if (CollUtil.isEmpty(modeList)) {
            return new ArrayList<>();
        }
        
        // 2. 收集所有进度款模式ID
        List<Long> modeIds = modeList.stream()
                .map(ProgressPaymentModeRespVO::getId)
                .collect(java.util.stream.Collectors.toList());
        
        // 3. 批量查询所有关联的清单数据
        List<ProgressDivisionDO> divisionList = progressDivisionMapper.selectListByProgressPaymentModeIds(modeIds);
        
        // 4. 按 progressPaymentModeId 分组
        Map<Long, List<ProgressDivisionDO>> divisionMap = new HashMap<>();
        for (ProgressDivisionDO division : divisionList) {
            divisionMap.computeIfAbsent(division.getProgressPaymentModeId(), k -> new ArrayList<>())
                    .add(division);
        }
        
        // 5. 构建返回结果
        List<ProgressPaymentModeWithDivisionsRespVO> result = new ArrayList<>();
        for (ProgressPaymentModeRespVO mode : modeList) {
            ProgressPaymentModeWithDivisionsRespVO respVO = new ProgressPaymentModeWithDivisionsRespVO();
            BeanUtils.copyProperties(mode, respVO);
            
            // 设置关联的清单列表
            List<ProgressDivisionDO> divisions = divisionMap.get(mode.getId());
            if (CollUtil.isNotEmpty(divisions)) {
                List<ProgressDivisionSimpleVO> children = divisions.stream()
                        .map(this::convertToSimpleVO)
                        .collect(java.util.stream.Collectors.toList());
                respVO.setChildren(children);
            } else {
                respVO.setChildren(new ArrayList<>());
            }
            
            result.add(respVO);
        }
        
        return result;
    }

    /**
     * 转换为简要信息 VO
     */
    private ProgressDivisionSimpleVO convertToSimpleVO(ProgressDivisionDO division) {
        ProgressDivisionSimpleVO simpleVO = new ProgressDivisionSimpleVO();
//        simpleVO.setId(division.getId());
        simpleVO.setBoqDivisionId(division.getBoqDivisionId());
        simpleVO.setPeriodValue(division.getPeriodValue());
        return simpleVO;
    }
}
