package com.ningdatech.pmapi.projectdeclared.manage;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Maps;
import com.ningdatech.basic.function.VUtils;
import com.ningdatech.pmapi.common.enumeration.ProjectProcessStageEnum;
import com.ningdatech.pmapi.common.helper.UserInfoHelper;
import com.ningdatech.pmapi.projectdeclared.model.dto.ProjectConditionDTO;
import com.ningdatech.pmapi.projectlib.enumeration.ProjectStatusEnum;
import com.ningdatech.pmapi.projectlib.model.entity.Project;
import com.ningdatech.pmapi.projectlib.model.entity.ProjectInst;
import com.ningdatech.pmapi.projectlib.service.IProjectInstService;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import com.ningdatech.pmapi.user.security.auth.model.UserFullInfoDTO;
import com.ningdatech.pmapi.user.util.LoginUserUtil;
import com.wflow.bean.entity.WflowModels;
import com.wflow.exception.BusinessException;
import com.wflow.workflow.bean.dto.OrgInfoDTO;
import com.wflow.workflow.bean.dto.ProcessInstanceUserDto;
import com.wflow.workflow.bean.vo.ProcessStartParamsVo;
import com.wflow.workflow.service.ProcessInstanceService;
import com.wflow.workflow.service.ProcessModelService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;

/**
 * @Classname ReviewByDeptJointManage
 * @Description 部门联审
 * @Date 2023/2/17 14:48
 * @Author PoffyZhang
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class ReviewByDeptJointManage {

    private final IProjectService projectService;

    private final ProcessModelService processModelService;

    private final ProcessInstanceService processService;

    private final IProjectInstService projectInstService;

    private final UserInfoHelper userInfoHelper;
    private final DefaultDeclaredProjectManage declaredProjectManage;
    private final DefaultDeclaredProjectManage defaultDeclaredProjectManage;

    /**
     * 部门联审
     * @param project
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean startTheProcess(Project project) {
        Long userId = LoginUserUtil.getUserId();
        VUtils.isTrue(Objects.isNull(userId)).throwMessage("获取登录用户失败!");

        VUtils.isTrue(Objects.isNull(project.getId())).throwMessage("提交失败 缺少项目ID!");
        Project projectInfo = projectService.getById(project.getId());
        VUtils.isTrue(Objects.isNull(projectInfo)).throwMessage("提交失败 此项目不存在!");
        String regionCode = projectInfo.getAreaCode();

        WflowModels model = processModelService.getOne(Wrappers.lambdaQuery(WflowModels.class)
                .eq(WflowModels::getRegionCode, regionCode)
                .eq(WflowModels::getProcessType, ProjectProcessStageEnum.DEPARTMENT_JOINT_APPROVAL_PROCESS.getCode())
                .last("limit 1"));

        if (Objects.isNull(model)) {
            log.error("此 【{}】区域找不到 部门联审申报流程配置", regionCode);
            throw new BusinessException(String.format("此 【%s】区域找不到 部门联审申报流程配置", regionCode));
        }
        //要判断 项目当前状态 是不是 部门联审
        VUtils.isTrue(!ProjectStatusEnum.DEPARTMENT_JOINT_REVIEW.getCode().equals(projectInfo.getStatus()) ||
                        !ProjectStatusEnum.NOT_APPROVED.getCode().equals(projectInfo.getStage()))
                .throwMessage("提交失败 该项目不是 省级部门联审状态状态或者未立项阶段");

        // 再判断 该项目是否 真实走完 预审审批 并且提取出 提交人
        VUtils.isTrue(Objects.isNull(projectInfo.getSponsor()))
                .throwMessage("提交失败 项目信息 缺少项目发起人!");

        ProcessStartParamsVo params = new ProcessStartParamsVo();
        //发起人的信息
        params.setUser(declaredProjectManage.buildUser(projectInfo.getSponsor()));
        params.setProcessUsers(Collections.emptyMap());

        Map<String, Object> formData = Maps.newHashMap();
        //放入条件判断的项目字段
        ProjectConditionDTO conditionDto = new ProjectConditionDTO();
        BeanUtils.copyProperties(projectInfo, conditionDto);
        formData.putAll(
                JSON.parseObject(JSON.toJSONString(conditionDto), new TypeReference<Map<String, Object>>() {
                })
        );
        params.setFormData(formData);

        // 获取发起单位、发起单位主管单位信息
        Map<String, OrgInfoDTO> orgModelMap = defaultDeclaredProjectManage.getOrgModelInfo(userId, model);
        String instanceId = processService.newStartProcess(model.getProcessDefId(),model.getFormId(), params,orgModelMap);
        log.info("部门联审申报成功 【{}】", instanceId);

        //保存项目信息
        if(!modifyProject(projectInfo, instanceId)){
            return Boolean.FALSE;
        }

        return Boolean.TRUE;
    }

    private Boolean modifyProject(Project project, String instanceId) {
        //流程启动之后 入库项目 重要业务信息 用于列表查询 展示
        try {
            project.setUpdateOn(LocalDateTime.now());
            project.setInstCode(instanceId);
            project.setStage(ProjectStatusEnum.NOT_APPROVED.getCode());
            project.setStatus(ProjectStatusEnum.UNDER_INTERNAL_AUDIT.getCode());
            projectService.updateById(project);
            //保存项目和实例的关系
            ProjectInst projectInst = new ProjectInst();
            projectInst.setProjectId(project.getId());
            projectInst.setInstCode(instanceId);
            projectInst.setCreatOn(LocalDateTime.now());
            projectInst.setUpdateOn(LocalDateTime.now());
            projectInst.setInstType(ProjectProcessStageEnum.DEPARTMENT_JOINT_APPROVAL_PROCESS.getCode());
            projectInstService.save(projectInst);
        } catch (Exception e) {
            log.error("部门联审 修改项目信息 错误 ", e);
            throw new BusinessException("部门联审 修改项目信息 错误 :" + e.getMessage());
        }
        return Boolean.TRUE;
    }
}
