package com.maintain.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.maintain.business.domain.ErpRepairFormProject;
import com.maintain.business.domain.bo.ErpRepairFormProjectDispatchBatchBo;
import com.maintain.business.domain.vo.ErpUserVo;
import com.maintain.business.mapper.ErpRepairFormProjectMapper;
import com.maintain.business.mapper.ErpUserMapper;
import com.maintain.common.enums.IsEnableStatus;
import com.maintain.common.utils.StringUtils;
import com.maintain.common.core.page.TableDataInfo;
import com.maintain.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.maintain.business.domain.bo.ErpRepairFormProjectDispatchBo;
import com.maintain.business.domain.vo.ErpRepairFormProjectDispatchVo;
import com.maintain.business.domain.ErpRepairFormProjectDispatch;
import com.maintain.business.mapper.ErpRepairFormProjectDispatchMapper;
import com.maintain.business.service.IErpRepairFormProjectDispatchService;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;

/**
 * 报修单-报修项目-派工Service业务层处理
 *
 * @author liushuai
 * @date 2025-04-01
 */
@RequiredArgsConstructor
@Service
public class ErpRepairFormProjectDispatchServiceImpl implements IErpRepairFormProjectDispatchService {

    private final ErpRepairFormProjectDispatchMapper baseMapper;
    private final ErpRepairFormProjectMapper projectMapper;
    private final ErpUserMapper userMapper;

    /**
     * 查询报修单-报修项目-派工
     */
    @Override
    public ErpRepairFormProjectDispatchVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询报修单-报修项目-派工列表
     */
    @Override
    public TableDataInfo<ErpRepairFormProjectDispatchVo> queryPageList(ErpRepairFormProjectDispatchBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ErpRepairFormProjectDispatch> lqw = buildQueryWrapper(bo);
        Page<ErpRepairFormProjectDispatchVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询报修单-报修项目-派工列表
     */
    @Override
    public List<ErpRepairFormProjectDispatchVo> queryList(ErpRepairFormProjectDispatchBo bo) {
        LambdaQueryWrapper<ErpRepairFormProjectDispatch> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ErpRepairFormProjectDispatch> buildQueryWrapper(ErpRepairFormProjectDispatchBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ErpRepairFormProjectDispatch> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getRepairFormId() != null, ErpRepairFormProjectDispatch::getRepairFormId, bo.getRepairFormId());
        lqw.eq(bo.getRepairFormProjectId() != null, ErpRepairFormProjectDispatch::getRepairFormProjectId, bo.getRepairFormProjectId());
        lqw.eq(bo.getDeptId() != null, ErpRepairFormProjectDispatch::getDeptId, bo.getDeptId());
        lqw.like(StringUtils.isNotBlank(bo.getDeptName()), ErpRepairFormProjectDispatch::getDeptName, bo.getDeptName());
        lqw.eq(bo.getGroupId() != null, ErpRepairFormProjectDispatch::getGroupId, bo.getGroupId());
        lqw.like(StringUtils.isNotBlank(bo.getGroupName()), ErpRepairFormProjectDispatch::getGroupName, bo.getGroupName());
        lqw.eq(bo.getMaintainUserId() != null, ErpRepairFormProjectDispatch::getMaintainUserId, bo.getMaintainUserId());
        lqw.like(StringUtils.isNotBlank(bo.getMaintainUserName()), ErpRepairFormProjectDispatch::getMaintainUserName, bo.getMaintainUserName());
        lqw.eq(bo.getMaintainUserState() != null, ErpRepairFormProjectDispatch::getMaintainUserState, bo.getMaintainUserState());
        lqw.eq(bo.getPostId() != null, ErpRepairFormProjectDispatch::getPostId, bo.getPostId());
        lqw.like(StringUtils.isNotBlank(bo.getPostName()), ErpRepairFormProjectDispatch::getPostName, bo.getPostName());
        lqw.eq(bo.getDispatchManHour() != null, ErpRepairFormProjectDispatch::getDispatchManHour, bo.getDispatchManHour());
        lqw.eq(bo.getDeductManHour() != null, ErpRepairFormProjectDispatch::getDeductManHour, bo.getDeductManHour());
        lqw.eq(bo.getActualManHour() != null, ErpRepairFormProjectDispatch::getActualManHour, bo.getActualManHour());
        return lqw;
    }

    /**
     * 新增报修单-报修项目-派工
     */
    @Override
    public Boolean insertByBo(ErpRepairFormProjectDispatchBo bo) {
        ErpRepairFormProjectDispatch add = BeanUtil.toBean(bo, ErpRepairFormProjectDispatch.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 新增报修单-报修项目-派工
     *
     * @param bo
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean insertBatchByBo(ErpRepairFormProjectDispatchBatchBo bo) {
        ErpRepairFormProject formProject = projectMapper.selectById(bo.getProjectId());

        // 删除原有绑定
        LambdaQueryWrapper<ErpRepairFormProjectDispatch> lqw = Wrappers.lambdaQuery();
        lqw.eq(ErpRepairFormProjectDispatch::getRepairFormProjectId, bo.getProjectId());
        BigDecimal totalActualManHour = baseMapper.selectList(lqw)
                .stream()
            .map(ErpRepairFormProjectDispatch::getActualManHour).reduce(BigDecimal.ZERO, BigDecimal::add);
        baseMapper.delete(lqw);
        // 汇总原总工时

        //总工时均分
        BigDecimal hour = formProject.getStandardManHour().divide(
                BigDecimal.valueOf(bo.getDispatchIdList().size()), 1, RoundingMode.HALF_DOWN
        );
        BigDecimal totalHour = hour.multiply(BigDecimal.valueOf(bo.getDispatchIdList().size()));
        BigDecimal lostHour = formProject.getStandardManHour().subtract(totalHour);
        // 批量新增派工人员列表
        List<ErpRepairFormProjectDispatch> collect = bo.getDispatchIdList().stream().map(item -> {
            ErpRepairFormProjectDispatch projectDispatch = new ErpRepairFormProjectDispatch();
            ErpUserVo userVo = userMapper.selectVoById(item);
            projectDispatch.setRepairFormId(formProject.getRepairFormId());
            projectDispatch.setRepairFormProjectId(formProject.getId());
            projectDispatch.setDeptId(userVo.getDeptId());
            projectDispatch.setDeptName(userVo.getDeptName());
            projectDispatch.setGroupId(userVo.getSiteGroupId());
            projectDispatch.setGroupName(userVo.getSiteGroupName());
            projectDispatch.setPostId(userVo.getPostId());
            projectDispatch.setPostName(userVo.getPostName());
            projectDispatch.setMaintainUserId(userVo.getId());
            projectDispatch.setMaintainUserName(userVo.getName());
            projectDispatch.setMaintainJobNumber(userVo.getJobNumber());
            projectDispatch.setMaintainUserState(userVo.getState());
            projectDispatch.setDispatchManHour(hour);
            projectDispatch.setActualManHour(hour);
//            projectDispatch.setDeductManHour(hour);
            return projectDispatch;
        }).collect(Collectors.toList());
        //处理最后一个
        if (bo.getDispatchIdList().size() > 1) {
            ErpRepairFormProjectDispatch projectDispatch = collect.get(collect.size() - 1);
            projectDispatch.setDispatchManHour(projectDispatch.getDispatchManHour().add(lostHour));
            projectDispatch.setActualManHour(hour);
        }

        formProject.setIsDispatch(IsEnableStatus.YES.getCode());
        formProject.setActualTime(formProject.getStandardManHour());
        projectMapper.updateById(formProject);
        return baseMapper.insertBatch(collect);
    }

    /**
     * 修改报修单-报修项目-派工
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(ErpRepairFormProjectDispatchBo bo) {
        ErpRepairFormProjectDispatch projectDispatch = baseMapper.selectById(bo.getId());
        projectDispatch.setDispatchManHour(bo.getDispatchManHour());
        projectDispatch.setActualManHour(bo.getDispatchManHour().subtract(bo.getDeductManHour()));
        projectDispatch.setDeductManHour(bo.getDeductManHour());
        boolean flag = baseMapper.updateById(projectDispatch) > 0;

        updateFormProject(projectDispatch.getRepairFormProjectId());

        return flag;
    }

    @Override
    public Boolean updateBatchByBo(List<ErpRepairFormProjectDispatchBo> boList) {
        if (CollUtil.isEmpty(boList)){
            return false;
        }

        List<ErpRepairFormProjectDispatch> dispatchList = boList.stream().map(bo -> {
            ErpRepairFormProjectDispatch projectDispatch = new ErpRepairFormProjectDispatch();
            projectDispatch.setId(bo.getId());
            projectDispatch.setDispatchManHour(bo.getDispatchManHour());
            projectDispatch.setActualManHour(bo.getDispatchManHour().subtract(bo.getDeductManHour()));
            projectDispatch.setDeductManHour(bo.getDeductManHour());
            return projectDispatch;
        }).collect(Collectors.toList());
        baseMapper.updateBatchById(dispatchList);

        //计算总工时
        BigDecimal reduce = dispatchList.stream().map(ErpRepairFormProjectDispatch::getActualManHour).reduce(BigDecimal.ZERO, BigDecimal::add);
        ErpRepairFormProject project = new ErpRepairFormProject();
        project.setId(boList.get(0).getRepairFormProjectId());
        project.setActualTime(reduce);
        projectMapper.updateById(project);

        return true;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ErpRepairFormProjectDispatch entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除报修单-报修项目-派工
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        Iterator<Long> iterator = ids.iterator();
        Long id = iterator.hasNext() ? iterator.next() : null;
        ErpRepairFormProjectDispatch projectDispatch = baseMapper.selectById(id);

        boolean flag = baseMapper.deleteBatchIds(ids) > 0;

        updateFormProject(projectDispatch.getRepairFormProjectId());

        return flag;
    }

    /**
     * 更新报修单-报修项目实际时间
     * @param projectId
     */
    private void updateFormProject(Long projectId){
        List<ErpRepairFormProjectDispatch> formProjectDispatches = baseMapper.selectList(Wrappers.<ErpRepairFormProjectDispatch>lambdaQuery()
                .eq(ErpRepairFormProjectDispatch::getRepairFormProjectId, projectId));
        //计算总工时
        BigDecimal reduce = formProjectDispatches.stream().map(ErpRepairFormProjectDispatch::getActualManHour).reduce(BigDecimal.ZERO, BigDecimal::add);
        ErpRepairFormProject project = new ErpRepairFormProject();
        project.setId(projectId);
        project.setActualTime(reduce);
        projectMapper.updateById(project);
    }
}
