package com.ruoyi.oa.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.oa.domain.OaProjectScheduleStep;
import com.ruoyi.oa.domain.OaScheduleTemplate;
import com.ruoyi.oa.domain.OaScheduleTemplateStep;
import com.ruoyi.oa.domain.bo.OaProjectScheduleStepBo;
import com.ruoyi.oa.domain.bo.OaScheduleTemplateStepBo;
import com.ruoyi.oa.domain.vo.OaProjectScheduleStepVo;
import com.ruoyi.oa.domain.vo.OaScheduleTemplateStepVo;
import com.ruoyi.oa.domain.vo.OaScheduleTemplateVo;
import com.ruoyi.oa.mapper.OaScheduleTemplateMapper;
import com.ruoyi.oa.service.IOaProjectScheduleStepService;
import com.ruoyi.oa.service.IOaScheduleTemplateStepService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.oa.domain.bo.OaProjectScheduleBo;
import com.ruoyi.oa.domain.vo.OaProjectScheduleVo;
import com.ruoyi.oa.domain.OaProjectSchedule;
import com.ruoyi.oa.mapper.OaProjectScheduleMapper;
import com.ruoyi.oa.service.IOaProjectScheduleService;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Collection;

/**
 * 项目进度Service业务层处理
 *
 * @author haka
 * @date 2025-05-08
 */
@RequiredArgsConstructor
@Service
public class OaProjectScheduleServiceImpl implements IOaProjectScheduleService {

    private final OaProjectScheduleMapper baseMapper;

    private final OaScheduleTemplateMapper scheduleTemplateMapper;

    private final IOaScheduleTemplateStepService scheduleTemplateStepService;

    private final IOaProjectScheduleStepService projectScheduleStepService;

    /**
     * 查询项目进度
     */
    @Override
    public OaProjectScheduleVo queryById(Long scheduleId){
        return baseMapper.selectVoById(scheduleId);
    }

    /**
     * 查询项目进度列表
     */
    @Override
    public TableDataInfo<OaProjectScheduleVo> queryPageList(OaProjectScheduleBo bo, PageQuery pageQuery) {
        QueryWrapper<OaProjectSchedule> lqw = buildQueryWrapper(bo);
        Page<OaProjectScheduleVo> result = baseMapper.selectVoPagePlus(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询项目进度列表
     */
    @Override
    public List<OaProjectScheduleVo> queryList(OaProjectScheduleBo bo) {
        QueryWrapper<OaProjectSchedule> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private QueryWrapper<OaProjectSchedule> buildQueryWrapper(OaProjectScheduleBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<OaProjectSchedule> lqw = Wrappers.query();
        lqw.eq("ops.del_flag", 0);
        lqw.eq(bo.getProjectId() != null,"ops.project_id", bo.getProjectId());
        lqw.eq(bo.getTemplateId() != null, "ops.template_id", bo.getTemplateId());
        lqw.eq(bo.getCurrentStep() != null, "ops.current_step", bo.getCurrentStep());
        lqw.eq(bo.getStatus() != null, "ops.status", bo.getStatus());
        lqw.gt(bo.getPrePay()!=null&&bo.getPrePay()>0, "op.pre_pay", 0);
        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
                "op.begin_time", params.get("beginCreateTime"), params.get("endCreateTime"));
        return lqw;
    }

    /**
     * 新增项目进度
     */
    @Override
    public Boolean insertByBo(OaProjectScheduleBo bo) {

        if (bo.getMode().equals("custom")){
            // 生成模板
            OaScheduleTemplate oaScheduleTemplate = new OaScheduleTemplate();
            oaScheduleTemplate.setTemplateName("自动生成_"+ DateUtils.getTime() +"_"+LoginHelper.getNickName());
            oaScheduleTemplate.setStatus(1L);
            oaScheduleTemplate.setCreateBy(LoginHelper.getNickName());
            scheduleTemplateMapper.insert(oaScheduleTemplate);

            // 生成模板对应的步骤
            Long templateId = oaScheduleTemplate.getTemplateId();
            for (int i = 1; i <= bo.getSteps().size(); i++) {
                OaScheduleTemplateStepBo step = getOaScheduleTemplateStepBo(bo, i, templateId);
                scheduleTemplateStepService.insertByBo(step);
            }
            bo.setTemplateId(templateId);
        }

        bo.setCurrentStep(1L);
        OaProjectSchedule add = BeanUtil.toBean(bo, OaProjectSchedule.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setScheduleId(add.getScheduleId());
        }
        Long templateId = bo.getTemplateId();
        OaScheduleTemplateStepBo oaScheduleTemplateStep = new OaScheduleTemplateStepBo();
        oaScheduleTemplateStep.setTemplateId(templateId);
        List<OaScheduleTemplateStepVo> oaScheduleTemplateStepVos = scheduleTemplateStepService.queryList(oaScheduleTemplateStep);

        for (int i = 0; i < bo.getSteps().size(); i++) {

            OaProjectScheduleStepBo step = bo.getSteps().get(i);
            step.setScheduleId(add.getScheduleId());
            OaScheduleTemplateStepVo oaScheduleTemplateStepVo = oaScheduleTemplateStepVos.get(i);
            step.setStepOrder(oaScheduleTemplateStepVo.getStepOrder());
            step.setBatchId(1L);
            step.setHeader(oaScheduleTemplateStepVo.getHeader());
            if (i==0){
                step.setActualStart(new Date());
            }
            projectScheduleStepService.insertByBo(step);
        }
        return flag;
    }

    private static OaScheduleTemplateStepBo getOaScheduleTemplateStepBo(OaProjectScheduleBo bo, int i, Long templateId) {
        OaProjectScheduleStepBo projectScheduleStep = bo.getSteps().get(i-1);
        OaScheduleTemplateStepBo step = new OaScheduleTemplateStepBo();
        step.setStepName(projectScheduleStep.getStepName());
        step.setDescription(projectScheduleStep.getDescription());
        step.setTemplateId(templateId);
        step.setStepOrder((long) i);
        step.setExpectedDays(projectScheduleStep.getExpectedDays());
        step.setCreateBy(LoginHelper.getNickName());
        return step;
    }

    /**
     * 修改项目进度
     */
    @Override
    public Boolean updateByBo(OaProjectScheduleBo bo) {
        OaProjectSchedule update = BeanUtil.toBean(bo, OaProjectSchedule.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

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

    /**
     * 批量删除项目进度
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean complete(OaProjectScheduleBo bo) {
        // 0首先判断是否到最后一部
        OaProjectScheduleStepVo scheduleStepVo =  projectScheduleStepService.maxStepByScheduleId(bo.getScheduleId());
        // 此处被分为了两种情况
        if (scheduleStepVo.getStepOrder()>bo.getCurrentStep()){
            // 1未完成全部进度，此时将currentStep更新到下一位 然后将当前的step的完成标志status改为1标志完成
            projectScheduleStepService.updateByStepAndScheduleId(bo.getCurrentStep(),bo.getScheduleId());
            bo.setCurrentStep(bo.getCurrentStep()+1L);
            OaProjectScheduleStepVo stepVo = projectScheduleStepService.selectByCurrentStepAndScheduleId(bo.getCurrentStep(),bo.getScheduleId());
            stepVo.setActualStart(new Date());
            OaProjectScheduleStepBo update = BeanUtil.toBean(stepVo, OaProjectScheduleStepBo.class);
            projectScheduleStepService.updateByBo(update);
        }else{
            // 将最后一步完成
            projectScheduleStepService.updateByStepAndScheduleId(bo.getCurrentStep(),bo.getScheduleId());
            // 2完成了全部进度，此时将此对象的status直接改为2代表完成了全部操作
            OaProjectScheduleStepVo stepVo = projectScheduleStepService.selectByCurrentStepAndScheduleId(bo.getCurrentStep(),bo.getScheduleId());
            OaProjectScheduleStepBo update = BeanUtil.toBean(stepVo, OaProjectScheduleStepBo.class);
            update.setActualEnd(new Date());
            projectScheduleStepService.updateByBo(update);
            bo.setStatus(2L);
        }
        return updateByBo(bo);
    }
}
