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

import cn.hutool.core.collection.CollUtil;
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
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.PlanDateSaveReqVO;
import com.zt.plat.module.base.dal.dao.plandate.PlanDateMapper;
import com.zt.plat.module.base.dal.dataobject.plandate.PlanDateDO;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

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

import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.pojo.PageParam;
import com.zt.plat.framework.common.util.object.BeanUtils;
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.framework.common.util.collection.CollectionUtils.convertList;
import static com.zt.plat.framework.common.util.collection.CollectionUtils.diffList;
import static com.zt.plat.module.base.enums.ErrorCodeConstants.PLAN_DATE_NOT_EXISTS;
import static com.zt.plat.module.base.enums.PlanConstants.ROOT_PARENT_ID;

/**
 * 计划数据 Service 实现类
 *
 * @author 后台管理-1
 */
@Service
@Validated
public class PlanDateServiceImpl implements PlanDateService {


    @Resource
    private PlanDateMapper planDateMapper;

    @Override
    public PlanDateRespVO createPlanDate(PlanDateSaveReqVO createReqVO) {
        // 插入
        PlanDateDO planDate = BeanUtils.toBean(createReqVO, PlanDateDO.class);
        planDateMapper.insert(planDate);
        // 返回
        return BeanUtils.toBean(planDate, PlanDateRespVO.class);
    }

    @Override
    public void updatePlanDate(PlanDateSaveReqVO updateReqVO) {
        // 校验存在
        validatePlanDateExists(updateReqVO.getId());
        // 更新
        PlanDateDO updateObj = BeanUtils.toBean(updateReqVO, PlanDateDO.class);
        planDateMapper.updateById(updateObj);
    }

    @Override
    public void deletePlanDate(Long id) {
        // 校验存在
        validatePlanDateExists(id);
        // 删除
        planDateMapper.deleteById(id);
    }

    @Override
    public void deletePlanDateListByIds(List<Long> ids) {
        // 校验存在
        validatePlanDateExists(ids);
        // 删除
        planDateMapper.deleteByIds(ids);
    }

    private void validatePlanDateExists(List<Long> ids) {
        List<PlanDateDO> list = planDateMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(PLAN_DATE_NOT_EXISTS);
        }
    }

    private void validatePlanDateExists(Long id) {
        if (planDateMapper.selectById(id) == null) {
            throw exception(PLAN_DATE_NOT_EXISTS);
        }
    }

    @Override
    public PlanDateDO getPlanDate(Long id) {
        return planDateMapper.selectById(id);
    }

    @Override
    public PageResult<PlanDateDO> getPlanDatePage(PlanDatePageReqVO pageReqVO) {
        return planDateMapper.selectPage(pageReqVO);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public PlanDateRespVO createPlanDateWithChildren(PlanDateSaveReqVO createReqVO) {
        // 1. 保存根节点（父节点）
        PlanDateDO rootPlanDate = BeanUtils.toBean(createReqVO, PlanDateDO.class);
        rootPlanDate.setId(null); // 新增时清空ID，使用数据库自增
        rootPlanDate.setParentId(ROOT_PARENT_ID); // 根节点父ID设为0
        planDateMapper.insert(rootPlanDate);

        // 2. 递归保存所有子节点
        recursiveSaveChildren(createReqVO.getChildren(), rootPlanDate.getId());

        // 3. 返回根节点响应
        return BeanUtils.toBean(rootPlanDate, PlanDateRespVO.class);
    }

    /**
     * 私有辅助方法：递归保存子节点
     * @param childrenVO 子节点VO列表
     * @param parentId 父节点ID
     */
    private void recursiveSaveChildren(List<PlanDateSaveReqVO> childrenVO, Long parentId) {
        // 子节点为空时直接返回
        if (CollUtil.isEmpty(childrenVO)) {
            return;
        }

        // 遍历子节点并保存
        for (PlanDateSaveReqVO childVO : childrenVO) {
            PlanDateDO childPlanDate = BeanUtils.toBean(childVO, PlanDateDO.class);
            childPlanDate.setId(null); // 新增时清空ID
            childPlanDate.setParentId(parentId); // 设置父节点ID
            planDateMapper.insert(childPlanDate);

            // 递归保存当前子节点的子节点（孙子节点）
            recursiveSaveChildren(childVO.getChildren(), childPlanDate.getId());
        }
    }

    /**
     * 查询所有计划数据并构造树形结构（适配前端展示）
     * @return 树形结构的计划数据RespVO列表
     */
    @Override
    public List<PlanDateRespVO> listPlanDateTree(PlanDatePageReqVO reqVO) {
        // 1. 全量查询所有未删除的计划数据
        List<PlanDateDO> allPlanDate = planDateMapper.selectList(
                new LambdaQueryWrapperX<PlanDateDO>()
                        .likeIfPresent(PlanDateDO::getPlanName, reqVO.getPlanName())
                        .eqIfPresent(PlanDateDO::getPlanCoding, reqVO.getPlanCoding())
                        .eqIfPresent(PlanDateDO::getParentId, reqVO.getParentId())
                        .eqIfPresent(PlanDateDO::getYear, reqVO.getYear())
                        .eqIfPresent(PlanDateDO::getInitialValue, reqVO.getInitialValue())
                        .eqIfPresent(PlanDateDO::getAverageValue, reqVO.getAverageValue())
                        .eqIfPresent(PlanDateDO::getSumValue, reqVO.getSumValue())
                        .eqIfPresent(PlanDateDO::getJanuary, reqVO.getJanuary())
                        .eqIfPresent(PlanDateDO::getFebruary, reqVO.getFebruary())
                        .eqIfPresent(PlanDateDO::getMarch, reqVO.getMarch())
                        .eqIfPresent(PlanDateDO::getApril, reqVO.getApril())
                        .eqIfPresent(PlanDateDO::getMay, reqVO.getMay())
                        .eqIfPresent(PlanDateDO::getJune, reqVO.getJune())
                        .eqIfPresent(PlanDateDO::getJuly, reqVO.getJuly())
                        .eqIfPresent(PlanDateDO::getAugust, reqVO.getAugust())
                        .eqIfPresent(PlanDateDO::getSeptember, reqVO.getSeptember())
                        .eqIfPresent(PlanDateDO::getOctober, reqVO.getOctober())
                        .eqIfPresent(PlanDateDO::getNovember, reqVO.getNovember())
                        .eqIfPresent(PlanDateDO::getDecember, reqVO.getDecember())
                        .betweenIfPresent(PlanDateDO::getCreateTime, reqVO.getCreateTime())
                        .orderByDesc(PlanDateDO::getId));
        if (CollUtil.isEmpty(allPlanDate)) {
            return Collections.emptyList();
        }

        // 保留你能正常映射的转换方式（无需修改）
        List<PlanDateRespVO> allVO = BeanUtils.toBean(allPlanDate, PlanDateRespVO.class);
        // 2. 构建父ID -> 子节点列表的映射（核心：适配父ID=0的根节点）
        Map<Long, List<PlanDateRespVO>> parentId2Children = allVO.stream()
                .collect(Collectors.groupingBy(
                        PlanDateRespVO::getParentId,
                        // 按计划名称排序，保证同级节点有序
                        Collectors.collectingAndThen(Collectors.toList(), list -> {
                            list.sort(Comparator.comparing(PlanDateRespVO::getPlanName));
                            return list;
                        })
                ));

        // 3. 递归构造树形结构，根节点为parentId=0的节点（核心修正）
        List<PlanDateRespVO> rootNodes = new ArrayList<>();
        for (PlanDateRespVO vo : allVO) {
            // 关键：匹配根节点父ID=0（而非null），这是你数据的实际根节点标识
            if (ROOT_PARENT_ID.equals(vo.getParentId())) {
                // 递归挂载子节点
                buildTreeChildren(vo, parentId2Children, 1); // 1代表根节点层级
                rootNodes.add(vo);
            }
        }

        // 根节点按名称排序
        rootNodes.sort(Comparator.comparing(PlanDateRespVO::getPlanName));
        return rootNodes;
    }

    /**
     * 递归为节点挂载子节点，并补充层级信息
     * @param parentNode 父节点
     * @param parentId2Children 父ID->子节点映射
     * @param level 节点层级（用于前端展示缩进）
     */
    private void buildTreeChildren(PlanDateRespVO parentNode,
                                   Map<Long, List<PlanDateRespVO>> parentId2Children,
                                   int level) {
        // 获取当前父节点的子节点列表
        List<PlanDateRespVO> children = parentId2Children.get(parentNode.getId());
        if (CollUtil.isEmpty(children)) {
            parentNode.setChildren(Collections.emptyList());
            return;
        }

        // 遍历子节点，递归挂载孙子节点
        for (PlanDateRespVO child : children) {
            buildTreeChildren(child, parentId2Children, level + 1);
        }

        // 挂载子节点到父节点（适配PlanDateRespVO的children字段）
        parentNode.setChildren(children);
    }
}