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

import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.salary.BpmOASalaryCreateReqVO;
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOASalaryConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.financialpayment.FinancialPaymentDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOASalaryDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOASalaryMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.service.financialpayment.FinancialPaymentService;
import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.smartfactory.api.staffSalary.StaffSalaryApi;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_SALARY_NOT_EXISTS;

/**
 * OA 薪资付款申请 Service 实现类
 *
 * @author 符溶馨
 */
@Service
@Validated
public class BpmOASalaryServiceImpl extends BpmOABaseService implements BpmOASalaryService{

    /**
     * OA 薪资付款对应的流程定义 KEY
     */
    public static final String PROCESS_KEY = "oa_salary_2";

    @Resource
    private BpmOASalaryMapper salaryMapper;

    @Resource
    private BpmProcessInstanceService processInstanceService;

    @Resource
    private BpmHistoryProcessInstanceService historyProcessInstanceService;

    @Resource
    private DeptApi deptApi;

    @Resource
    private AdminUserApi userApi;

    @Resource
    private FinancialPaymentService financialPaymentService;

    @Resource
    private StaffSalaryApi staffSalaryApi;

    @Override
    public Long createSalary(Long userId, BpmOASalaryCreateReqVO createReqVO) {

        //插入OA 薪资付款申请
        BpmOASalaryDO salary = BpmOASalaryConvert.INSTANCE.convert(createReqVO).setUserId(userId)
                .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
        salaryMapper.insert(salary) ;

        // 配置申请公司或工厂部门flag
        Map<String, Object> processInstanceVariables = new HashMap<>();
        if (createReqVO.getDeptType() == 1) {
            // 获取申请公司信息
            DeptRespDTO dto = deptApi.getDept(salary.getCompanyDeptId()).getCheckedData();
            processInstanceVariables.put("company_dept_flag", dto.getFlag());
        }
        processInstanceVariables.put("dept_type", createReqVO.getDeptType());
        // 发起 BPM 流程
        String processInstanceId = processInstanceService.createProcessInstance(userId,
                new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
                        .setVariables(processInstanceVariables).setBusinessKey(String.valueOf(salary.getId())));

        // 将工作流的编号，更新到 OA 用章单中
        salaryMapper.updateById(new BpmOASalaryDO().setId(salary.getId()).setProcessInstanceId(processInstanceId));

        // 判断是否为重新发起的流程
        if (createReqVO.getProcessInstanceId() != null && createReqVO.getResult() == 3) {

            historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, createReqVO.getProcessInstanceId());
        }

        List<UploadUserFile> fileItems = createReqVO.getFileItems() ;
        //这里的逻辑，如果fileItems不为空，且有数据，那么说明是上传了附件的，则需要更工作流文件表对应的实例Id
        if (fileItems != null && !fileItems.isEmpty()) {
            uploadBpmFileProcessInstanceId(processInstanceId,fileItems) ;
        }

        // 同步更新 员工薪资表已发放工资状态
        staffSalaryApi.updateIsGrant(salary.getStaffSalaryIds(), 1);

        return salary.getId();
    }

    @Override
    public void updateSalaryResult(String processInstanceId, Long id, Integer result) {
        BpmOASalaryDO salaryDO = validateLeaveExists(id);
        salaryMapper.updateById(new BpmOASalaryDO().setId(id).setResult(result));

        //审核通过 （最后节点）
        if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) {

            ProcessInstance instance = processInstanceService.getProcessInstance(processInstanceId);

            if (instance.isEnded()) {

                BpmProcessInstanceExtDO processInstance = processInstanceService.getProcessInstanceDO(processInstanceId);
                // -- 插入到财务支付表中
                CommonResult<AdminUserRespDTO> user = userApi.getUser(salaryDO.getUserId());

                financialPaymentService.save(new FinancialPaymentDO()
                        .setUserId(salaryDO.getUserId())
                        .setDeptId(user.getData() == null ? null : user.getData().getDeptId())
                        .setProcessInstanceId(salaryDO.getProcessInstanceId())
                        .setReason(salaryDO.getReason())
                        .setObjectId(id)
                        .setType(6)
                        .setStatus(0)
                        .setAmountPayable(salaryDO.getPaymentTotal())
                        .setProcessInstanceName(processInstance.getName())
                        .setBeginTime(processInstance.getCreateTime())
                        .setEndTime(processInstance.getEndTime())
                        .setCompanyId(salaryDO.getDeptType() == 1 ? salaryDO.getCompanyDeptId() : null)
                );
            }
        }

        // -- 自己取消
        // -- 审核拒绝
        //所有关联的采购申请改为 未支付状态
        if (BpmProcessInstanceResultEnum.REJECT.getResult().equals(result)
                || BpmProcessInstanceResultEnum.CANCEL.getResult().equals(result)
                || BpmProcessInstanceResultEnum.BACK.getResult().equals(result)) {

            // 还原员工薪资表已发放工资状态
            staffSalaryApi.updateIsGrant(salaryDO.getStaffSalaryIds(), 0);
        }
    }

    private BpmOASalaryDO validateLeaveExists(Long id) {
        BpmOASalaryDO salaryDO = salaryMapper.selectById(id);
        if (salaryDO == null) {
            throw exception(OA_SALARY_NOT_EXISTS);
        }
        return salaryDO;
    }

    @Override
    public BpmOASalaryDO getSalary(Long id) {

        return salaryMapper.selectById(id);
    }

    @Override
    public BpmOASalaryDO getByProcessInstanceId(String processInstanceId) {

        return salaryMapper.selectOne(BpmOASalaryDO::getProcessInstanceId, processInstanceId);
    }

    @Override
    public List<BpmOASalaryDO> getListByProcessInstanceIds(List<String> processInstanceIds) {

        return salaryMapper.selectList(BpmOASalaryDO::getProcessInstanceId, processInstanceIds);
    }
}
