package com.ningdatech.pmapi.projectlib.handle;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.ningdatech.basic.exception.BizException;
import com.ningdatech.basic.util.NdDateUtils;
import com.ningdatech.pmapi.common.constant.BizConst;
import com.ningdatech.pmapi.projectlib.enumeration.InstTypeEnum;
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.common.constant.CommonConst;
import com.ningdatech.pmapi.projectlib.service.IProjectService;
import com.ningdatech.pmapi.projectlib.utils.ProjectVersionUtil;
import com.ningdatech.pmapi.todocenter.constant.TodoCenterConstant;
import com.ningdatech.pmapi.todocenter.utils.BuildUserUtils;
import com.wflow.workflow.bean.dto.ProcessInstanceUserDto;
import com.wflow.workflow.bean.process.ProgressNode;
import com.wflow.workflow.bean.vo.ProcessDetailVO;
import com.wflow.workflow.bean.vo.ProcessProgressVo;
import com.wflow.workflow.enums.ProcessStatusEnum;
import com.wflow.workflow.enums.StepStatusEnum;
import com.wflow.workflow.service.ProcessInstanceService;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 单位内部审核处理
 *
 * @author CMM
 * @since 2023/02/24 14:35
 */
@Order(2)
@Component
public class UnitInnerAuditHandle extends AbstractProcessBusinessHandle {

    private final IProjectInstService projectInstService;

    private final ProcessInstanceService processInstanceService;
    private final BuildUserUtils buildUserUtils;
    private final ProjectVersionUtil projectVersionUtil;
    private final IProjectService projectService;

    private Integer order = 2;

    public UnitInnerAuditHandle(IProjectInstService projectInstService, ProcessInstanceService processInstanceService, BuildUserUtils buildUserUtils, ProjectVersionUtil projectVersionUtil, IProjectService projectService){
        this.projectInstService = projectInstService;
        this.processInstanceService = processInstanceService;
        this.buildUserUtils = buildUserUtils;
        this.projectVersionUtil = projectVersionUtil;
        this.projectService = projectService;
    }

    @Override
    void businessHandle(Long projectId, List<ProcessDetailVO> processSchedule) {
        ProcessDetailVO processDetailVO = new ProcessDetailVO();
        Project project = projectService.getById(projectId);
        List<Long> allVersionProjectIds = projectService.getAllVersionProjectId(project);
        // 根据项目ID查询出单位内部审核流程的流程状态
        ProjectInst projectInst = projectInstService.getOne(Wrappers.lambdaQuery(ProjectInst.class)
                .in(ProjectInst::getProjectId, allVersionProjectIds)
                .eq(ProjectInst::getInstType, InstTypeEnum.UNIT_INNER_AUDIT.getCode())
                .ne(ProjectInst::getInstCode, TodoCenterConstant.Declared.NULL_INST_CODE)
                .orderByDesc(ProjectInst::getCreatOn)
                .last(BizConst.LIMIT_1));
        ProcessProgressVo instanceDetail = null;

        // 未找到当前版本项目的单位内部审核流程且当前项目版本号大于1(是被驳回重新申报的项目)
        // 注意：已经在项目库中的项目，一定是单位内部审核已经开始的项目
        if (Objects.isNull(projectInst)) {
            if (project.getVersion() > CommonConst.VERSION_ONE){
                // 获取上个版本的信息
                instanceDetail = projectVersionUtil.getPreVerProcessInfo(projectId, InstTypeEnum.UNIT_INNER_AUDIT);
            }
        }else {
            String instCode = projectInst.getInstCode();
            instanceDetail = processInstanceService.getProgressInstanceDetail(null, instCode);
        }
        if (Objects.isNull(instanceDetail)){
            throw new BizException("未获取到单位内部审核流程详情!");
        }
        String status = instanceDetail.getStatus();
        if (ProcessStatusEnum.UNDER_REVIEW.getDesc().equals(status)){
            processDetailVO.setStepStatus(StepStatusEnum.ON_GOING);
        } else if (ProcessStatusEnum.BE_REJECTED.getDesc().equals(status)) {
            processDetailVO.setStepStatus(StepStatusEnum.REJECTED);
        } else if (ProcessStatusEnum.APPROVED.getDesc().equals(status)) {
            processDetailVO.setStepStatus(StepStatusEnum.COMPLETED);
        }

        // 装配节点审核人员信息
        List<ProgressNode> progressInfo = instanceDetail.getProgressInfo();
        if (CollUtil.isNotEmpty(progressInfo)) {
            buildUserUtils.buildUserByProcessInfo(progressInfo);
            // 根据流程处理详情获取流程完成时间
            if (StepStatusEnum.contains(processDetailVO.getStepStatus(),
                    Lists.newArrayList(StepStatusEnum.REJECTED,
                            StepStatusEnum.COMPLETED))) {
                // 如果是驳回,获取流程信息时可能
                ProgressNode progressNode = progressInfo.get(progressInfo.size() - 1);
                LocalDateTime finishTime = NdDateUtils.date2LocalDateTime(progressNode.getFinishTime());
                processDetailVO.setFinishTime(finishTime);
            }
        }else {
            LocalDateTime finishTime = NdDateUtils.date2LocalDateTime(instanceDetail.getStartTime());
            processDetailVO.setFinishTime(finishTime);
        }
        processDetailVO.setProcessProgressVo(instanceDetail);
        processDetailVO.setProcessName(CommonConst.UNIT_INNER_AUDIT);
        processSchedule.add(processDetailVO);
    }

    @Override
    Integer getOrder() {
        return order;
    }

    @Override
    void setOrder(Integer order) {
        this.order = order;
    }

    private void buildUser(List<ProgressNode> progressInfo, Map<String, ProcessInstanceUserDto> userMap) {
        for (ProgressNode progressNode : progressInfo) {
            progressNode.setUser(userMap.get(progressNode.getUserId()));
            if (CollUtil.isNotEmpty(progressNode.getChildren())) {
                buildUser(progressNode.getChildren(), userMap);
            }
        }
    }
}
