package cn.iocoder.yudao.module.bpm.service.oa;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.salesperformance.SalesPerformancePageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.salesperformance.SalesPerformanceSaveReqVO;
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOASalesPerformanceConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOASalesPerformanceDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOASalesPerformanceMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.hrm.api.salesperformancesettlement.SalesPerformanceSettlementApi;
import cn.iocoder.yudao.module.hrm.api.salesperformancesettlement.dto.SalesPerformanceSettlementDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.CAN_ONLY_APPLY_FOR_CURRENT_MONTH_PERFORMANCE_TARGET;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.THE_PROCESS_IS_BEING_APPROVED_OR_HAS_PASSED_THE_CURRENT_MONTH_AND_THE_APPLICATION_CANNOT_BE_REPEATED;

/**
 * 销售业绩目标申请OA Service 实现类
 *
 * @author 艾楷
 */
@Service
@Validated
public class BpmOASalesPerformanceServiceImpl extends ServiceImpl<BpmOASalesPerformanceMapper, BpmOASalesPerformanceDO> implements BpmOASalesPerformanceService {

    @Resource
    private BpmOASalesPerformanceMapper bpmOASalesPerformanceMapper;
    @Resource
    private BpmProcessInstanceApi processInstanceApi;
    @Resource
    private BpmHistoryProcessInstanceService historyProcessInstanceService;
    @Resource
    private BpmProcessInstanceService processInstanceService;
    @Resource
    private SalesPerformanceSettlementApi salesPerformanceSettlementApi;

    /**
     * OA 销售业绩目标申请OA对应的流程定义 KEY
     */
    public static final String PROCESS_KEY = "oa_sales_performance";

    @Override
    public Long createSalesPerformance(SalesPerformanceSaveReqVO createReqVO) {
        // 判断是否是当月的目标
        LocalDateTime now = LocalDateTime.now();
        String year = String.valueOf(now.getYear());
        String month = String.format("%02d", now.getMonthValue());
        Long userId = getLoginUserId();
        if (!year.equals(createReqVO.getYear()) || !month.equals(createReqVO.getMonth())) {
            throw exception(CAN_ONLY_APPLY_FOR_CURRENT_MONTH_PERFORMANCE_TARGET);
        }
        // 判断是否已经存在
        Long count = bpmOASalesPerformanceMapper.selectCount(new LambdaQueryWrapper<BpmOASalesPerformanceDO>()
                .eq(BpmOASalesPerformanceDO::getUserId, userId)
                .eq(BpmOASalesPerformanceDO::getYear, year)
                .eq(BpmOASalesPerformanceDO::getMonth, month)
                .in(BpmOASalesPerformanceDO::getResult, BpmProcessInstanceResultEnum.PROCESS.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult()));
        if (count > 0L) {
            throw exception(THE_PROCESS_IS_BEING_APPROVED_OR_HAS_PASSED_THE_CURRENT_MONTH_AND_THE_APPLICATION_CANNOT_BE_REPEATED);
        }
        BpmOASalesPerformanceDO bpmOASalesPerformanceDO = BpmOASalesPerformanceConvert.INSTANCE.convert(createReqVO).setUserId(userId)
                .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
        bpmOASalesPerformanceMapper.insert(bpmOASalesPerformanceDO);

        // 发起 BPM 流程
        String processInstanceId = processInstanceApi.createProcessInstance(userId,
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                        .setBusinessKey(String.valueOf(bpmOASalesPerformanceDO.getId()))).getCheckedData();

        bpmOASalesPerformanceMapper.updateById(bpmOASalesPerformanceDO.setProcessInstanceId(processInstanceId));
        // 判断是否为重新发起的流程
        if (createReqVO.getProcessInstanceId() != null && createReqVO.getResult() == 3) {
            historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, createReqVO.getProcessInstanceId());
        }
        // 返回
        return bpmOASalesPerformanceDO.getId();
    }

    @Override
    public void updateSalesPerformance(SalesPerformanceSaveReqVO updateReqVO) {
        // 更新
        BpmOASalesPerformanceDO updateObj = BeanUtils.toBean(updateReqVO, BpmOASalesPerformanceDO.class);
        bpmOASalesPerformanceMapper.updateById(updateObj);
    }

    @Override
    public void deleteSalesPerformance(Long id) {
        // 删除
        bpmOASalesPerformanceMapper.deleteById(id);
    }

    @Override
    public BpmOASalesPerformanceDO getSalesPerformance(Long id) {
        return bpmOASalesPerformanceMapper.selectById(id);
    }

    @Override
    public PageResult<BpmOASalesPerformanceDO> getSalesPerformancePage(SalesPerformancePageReqVO pageReqVO) {
        return bpmOASalesPerformanceMapper.selectPage(pageReqVO);
    }

    @Override
    public void updateSalesPerformanceResult(String processInstanceId, Long id, Integer result) {
        //审核通过 （最后节点）
        if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) {
            ProcessInstance instance = processInstanceService.getProcessInstance(processInstanceId);
            if (instance.isEnded()) {
                // -- 拿到当前的id set到表中目标表中
                // 当前用户
                BpmOASalesPerformanceDO bpmOASalesPerformanceDO = bpmOASalesPerformanceMapper.selectById(id);
                salesPerformanceSettlementApi.update(new SalesPerformanceSettlementDTO().setSalesPerformanceId(id)
                        .setYear(bpmOASalesPerformanceDO.getYear())
                        .setMonth(bpmOASalesPerformanceDO.getMonth())
                        .setUserId(bpmOASalesPerformanceDO.getUserId()));
            }
        }
        bpmOASalesPerformanceMapper.updateById(new BpmOASalesPerformanceDO().setId(id).setResult(result));
    }

}
