package org.dromara.progress.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.ObjectUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.facility.domain.FacMatrix;
import org.dromara.facility.service.IFacMatrixService;
import org.dromara.progress.domain.PgsProgressCategory;
import org.dromara.progress.domain.PgsProgressPlan;
import org.dromara.progress.domain.PgsProgressPlanDetail;
import org.dromara.progress.domain.dto.progressplan.PgsProgressPlanCreateReq;
import org.dromara.progress.domain.dto.progressplan.PgsProgressPlanQueryReq;
import org.dromara.progress.domain.dto.progressplandetail.PgsProgressPlanDetailCreateDto;
import org.dromara.progress.domain.vo.progressplan.PgsProgressPlanVo;
import org.dromara.progress.domain.vo.progressplandetail.PgsProgressPlanDetailNumVo;
import org.dromara.progress.mapper.PgsProgressPlanMapper;
import org.dromara.progress.service.IPgsProgressCategoryService;
import org.dromara.progress.service.IPgsProgressPlanDetailService;
import org.dromara.progress.service.IPgsProgressPlanService;
import org.dromara.project.service.IBusProjectService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 进度计划Service业务层处理
 *
 * @author lcj
 * @date 2025-05-27
 */
@Service
public class PgsProgressPlanServiceImpl extends ServiceImpl<PgsProgressPlanMapper, PgsProgressPlan>
    implements IPgsProgressPlanService {

    @Resource
    private IBusProjectService projectService;

    @Resource
    private IPgsProgressPlanDetailService progressPlanDetailService;

    @Resource
    private IPgsProgressCategoryService progressCategoryService;

    @Resource
    private IFacMatrixService matrixService;

    /**
     * 查询进度计划
     *
     * @param id 主键
     * @return 进度计划
     */
    @Override
    public PgsProgressPlanVo queryById(Long id) {
        PgsProgressPlan progressPlan = this.getById(id);
        if (progressPlan == null) {
            throw new ServiceException("进度计划信息不存在", HttpStatus.NOT_FOUND);
        }
        return this.getVo(progressPlan);
    }

    /**
     * 分页查询进度计划列表
     *
     * @param req       查询条件
     * @param pageQuery 分页参数
     * @return 进度计划分页列表
     */
    @Override
    public TableDataInfo<PgsProgressPlanVo> queryPageList(PgsProgressPlanQueryReq req, PageQuery pageQuery) {
        Page<PgsProgressPlan> result = this.page(pageQuery.build(), this.buildQueryWrapper(req));
        return TableDataInfo.build(this.getVoPage(result));
    }

    /**
     * 查询符合条件的进度计划列表
     *
     * @param req 查询条件
     * @return 进度计划列表
     */
    @Override
    public List<PgsProgressPlanVo> queryList(PgsProgressPlanQueryReq req) {
        List<PgsProgressPlan> list = this.list(this.buildQueryWrapper(req));
        return list.stream().map(this::getVo).toList();
    }

    /**
     * 新增进度计划
     *
     * @param req 进度计划
     * @return 新增进度计划主键
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insertByBo(PgsProgressPlanCreateReq req) {
        // 将实体类和 DTO 进行转换
        PgsProgressPlan progressPlan = new PgsProgressPlan();
        BeanUtils.copyProperties(req, progressPlan);
        // 数据校验
        Long projectId = progressPlan.getProjectId();
        if (projectService.getById(projectId) == null) {
            throw new ServiceException("对应项目不存在", HttpStatus.NOT_FOUND);
        }
        Long matrixId = progressPlan.getMatrixId();
        FacMatrix matrix = matrixService.getById(matrixId);
        if (matrix == null) {
            throw new ServiceException("对应方阵不存在", HttpStatus.NOT_FOUND);
        }
        Long progressCategoryId = progressPlan.getProgressCategoryId();
        this.validPlanNumber(req.getPlanNumber(), progressCategoryId);
        progressPlan.setMatrixName(matrix.getMatrixName());
        // 操作数据库
        boolean save = this.save(progressPlan);
        if (!save) {
            throw new ServiceException("新增进度计划失败，数据库异常", HttpStatus.ERROR);
        }
        // 更新进度计划详情
        Long id = progressPlan.getId();
        List<PgsProgressPlanDetailCreateDto> detailList = req.getDetailList();
        if (CollUtil.isNotEmpty(detailList)) {
            List<PgsProgressPlanDetail> detailList1 = detailList.stream().map(detail -> {
                PgsProgressPlanDetail progressPlanDetail = new PgsProgressPlanDetail();
                BeanUtils.copyProperties(detail, progressPlanDetail);
                progressPlanDetail.setProgressPlanId(id);
                progressPlanDetail.setProjectId(progressPlan.getProjectId());
                return progressPlanDetail;
            }).toList();
            boolean result = progressPlanDetailService.saveBatch(detailList1);
            if (!result) {
                throw new ServiceException("新增进度计划详情失败，数据库操作失败", HttpStatus.ERROR);
            }
        }
        // 更新进度分类计划总数量
        boolean update = progressCategoryService.lambdaUpdate()
            .eq(PgsProgressCategory::getId, progressCategoryId)
            .set(PgsProgressCategory::getPlanTotal, progressPlan.getPlanNumber())
            .update();
        if (!update) {
            throw new ServiceException("更新进度分类计划总数量失败，数据库操作失败", HttpStatus.ERROR);
        }
        return id;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(PgsProgressPlan entity) {
        // TODO 做一些数据校验,如唯一约束
        Long projectId = entity.getProjectId();
        if (projectService.getById(projectId) == null) {
            throw new ServiceException("对应项目不存在", HttpStatus.NOT_FOUND);
        }
        Long matrixId = entity.getMatrixId();
        if (matrixService.getById(matrixId) == null) {
            throw new ServiceException("对应方阵不存在", HttpStatus.NOT_FOUND);
        }
    }

    /**
     * 校验并批量删除进度计划信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        Long userId = LoginHelper.getUserId();
        List<PgsProgressPlan> progressPlanList = this.listByIds(ids);
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
            List<Long> projectId = progressPlanList.stream().map(PgsProgressPlan::getProjectId).toList();
            projectService.validAuth(projectId, userId);
        }
        return this.removeBatchByIds(ids);
    }

    /**
     * 获取进度计划视图对象
     *
     * @param progressPlan 进度计划对象
     * @return 进度计划视图对象
     */
    @Override
    public PgsProgressPlanVo getVo(PgsProgressPlan progressPlan) {
        // 对象转封装类
        PgsProgressPlanVo progressPlanVo = new PgsProgressPlanVo();
        if (progressPlan == null) {
            return progressPlanVo;
        }
        BeanUtils.copyProperties(progressPlan, progressPlanVo);
        // 获取详情列表
        Long id = progressPlan.getId();
        List<PgsProgressPlanDetail> detailList = progressPlanDetailService.lambdaQuery()
            .eq(PgsProgressPlanDetail::getProgressPlanId, id)
            .eq(PgsProgressPlanDetail::getProjectId, progressPlan.getProjectId())
            .list();
        progressPlanVo.setDetailList(progressPlanDetailService.getNumVoList(detailList));
        return progressPlanVo;
    }

    /**
     * 获取进度计划查询条件封装
     *
     * @param req 查询条件
     * @return 查询条件封装
     */
    @Override
    public LambdaQueryWrapper<PgsProgressPlan> buildQueryWrapper(PgsProgressPlanQueryReq req) {
        LambdaQueryWrapper<PgsProgressPlan> lqw = new LambdaQueryWrapper<>();
        if (req == null) {
            return lqw;
        }
        Long projectId = req.getProjectId();
        Long matrixId = req.getMatrixId();
        Long progressCategoryId = req.getProgressCategoryId();
        Date startDate = req.getStartDate();
        Date endDate = req.getEndDate();
        lqw.eq(ObjectUtils.isNotEmpty(projectId), PgsProgressPlan::getProjectId, projectId);
        lqw.eq(ObjectUtils.isNotEmpty(matrixId), PgsProgressPlan::getMatrixId, matrixId);
        lqw.eq(ObjectUtils.isNotEmpty(progressCategoryId), PgsProgressPlan::getProgressCategoryId, progressCategoryId);
        // 日期条件：大于startDate，小于endDate
        lqw.gt(ObjectUtils.isNotEmpty(startDate), PgsProgressPlan::getStartDate, startDate);
        lqw.lt(ObjectUtils.isNotEmpty(endDate), PgsProgressPlan::getEndDate, endDate);
        return lqw;
    }

    /**
     * 获取进度计划分页对象视图
     *
     * @param progressPlanPage 进度计划分页对象
     * @return 进度计划分页对象视图
     */
    @Override
    public Page<PgsProgressPlanVo> getVoPage(Page<PgsProgressPlan> progressPlanPage) {
        List<PgsProgressPlan> progressPlanList = progressPlanPage.getRecords();
        Page<PgsProgressPlanVo> progressPlanVoPage = new Page<>(
            progressPlanPage.getCurrent(),
            progressPlanPage.getSize(),
            progressPlanPage.getTotal());
        if (CollUtil.isEmpty(progressPlanList)) {
            return progressPlanVoPage;
        }
        // 获取详情列表
        List<Long> idList = progressPlanList.stream().map(PgsProgressPlan::getId).toList();
        List<PgsProgressPlanDetail> detailList = progressPlanDetailService.lambdaQuery()
            .in(PgsProgressPlanDetail::getProgressPlanId, idList).list();
        Map<Long, List<PgsProgressPlanDetail>> detailMap = detailList
            .stream().collect(Collectors.groupingBy(PgsProgressPlanDetail::getProgressPlanId));
        // 对象列表 => 封装对象列表
        List<PgsProgressPlanVo> progressPlanVoList = progressPlanList.stream().map(progressPlan -> {
            // 对象转封装类
            PgsProgressPlanVo progressPlanVo = new PgsProgressPlanVo();
            BeanUtils.copyProperties(progressPlan, progressPlanVo);
            // 获取详情列表
            Long id = progressPlan.getId();
            List<PgsProgressPlanDetailNumVo> numDetailList = new ArrayList<>();
            if (detailMap.containsKey(id)) {
                numDetailList = progressPlanDetailService.getNumVoList(detailMap.get(id));
            }
            progressPlanVo.setDetailList(numDetailList);
            return progressPlanVo;
        }).toList();
        progressPlanVoPage.setRecords(progressPlanVoList);
        return progressPlanVoPage;
    }

    /**
     * 校验计划数量是否合法
     *
     * @param planNumber         计划数量
     * @param progressCategoryId 进度类别id
     */
    @Override
    public void validPlanNumber(Long planNumber, Long progressCategoryId) {
        PgsProgressCategory progressCategory = progressCategoryService.getById(progressCategoryId);
        if (progressCategory == null) {
            throw new ServiceException("进度类别不存在", HttpStatus.NOT_FOUND);
        }
        BigDecimal total = progressCategory.getTotal();
        BigDecimal completed = progressCategory.getCompleted();
        BigDecimal planTotal = total.subtract(completed);
        if (planNumber.compareTo(planTotal.longValue()) > 0) {
            throw new ServiceException("计划数量不能大于剩余数量", HttpStatus.BAD_REQUEST);
        }
    }
}
