package cn.palmte.work.service;

import cn.palmte.work.bean.StatusEnum;
import cn.palmte.work.config.activiti.ActProcessKeyEnum;
import cn.palmte.work.config.activiti.ActProjectTypeEnum;
import cn.palmte.work.config.activiti.ActTaskIndexEnum;
import cn.palmte.work.model.Project;
import cn.palmte.work.model.ProjectTaskRecord;
import cn.palmte.work.model.ProjectTaskRecordRepository;
import cn.palmte.work.utils.ActUtil;
import cn.palmte.work.utils.InterfaceUtil;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import top.jfunc.common.db.QueryHelper;
import top.jfunc.common.db.utils.Pagination;

import java.util.*;


@Service
public class ProjectTaskRecordService {
    private static final Logger logger = LoggerFactory.getLogger(ProjectTaskRecordService.class);
    @Autowired
    private ProjectTaskRecordRepository projectTaskRecordRepository;

    @Autowired
    Pagination pagination;

    @Autowired
    private ActUtil actUtil;


    /**
     * 保存审批任务记录
     *
     * @param task
     * @param status
     * @param comment
     */
    public void saveTaskRecord(int projectId, Task task, int status, int taskIndex, String comment) {
        ProjectTaskRecord record = getProjectTaskRecord(projectId, task, status, taskIndex, comment);
        saveTaskRecord(record);
    }

    public void saveTaskRecordWithFileUrl(int projectId, Task task, int status,
                                          int taskIndex, String comment, String fileUrl) {
        ProjectTaskRecord record = getProjectTaskRecord(projectId, task, status, taskIndex, comment);
        record.setFileUrl(fileUrl);
        saveTaskRecord(record);
    }

    public void saveTaskRecordWithRollback(int projectId, ProjectTaskRecord oldRecord, String comment, String rollbackDesc) {
        ProjectTaskRecord record = new ProjectTaskRecord();
        record.setProjectId(projectId);
        record.setProcDefId(oldRecord.getProcDefId());
        record.setProcInsId(oldRecord.getProcInsId());
        record.setTaskDefKey(oldRecord.getTaskDefKey());
        record.setTaskName(oldRecord.getTaskName());
        record.setTaskComment(comment);
        record.setTaskStatus(ProjectTaskRecord.STATUS_ROLLBACK);
        record.setAssigneeId(InterfaceUtil.getAdminId() + "");
        record.setAssigneeName(InterfaceUtil.getAdmin().getRealName());
        record.setTaskIndex(ActTaskIndexEnum.COMMON.getIndex());
        record.setCreateTime(new Date());
        record.setRollbackRecordId(oldRecord.getId());
        record.setRollbackDesc(rollbackDesc);

        saveTaskRecord(record);
    }

    private void saveTaskRecord(ProjectTaskRecord record) {
        try {
            projectTaskRecordRepository.save(record);
        } catch (Exception e) {
            logger.error("", e);
        }
    }

    private ProjectTaskRecord getProjectTaskRecord(int projectId, Task task, int status, int taskIndex, String comment) {
        ProjectTaskRecord record = new ProjectTaskRecord();
        record.setProjectId(projectId);
        String procDefId = task.getProcessDefinitionId();
        record.setProcDefId(procDefId);
        record.setProcInsId(task.getProcessInstanceId());

        ActProjectTypeEnum projectTypeEnum = ActProjectTypeEnum.FOURCAL;
        if (procDefId.startsWith(ActProcessKeyEnum.SALE_CONTRACT.getKey())) {
            projectTypeEnum = ActProjectTypeEnum.SALE_CONTRACT;
        } else if (procDefId.startsWith(ActProcessKeyEnum.BUSINESS_PURCHASE.getKey())) {
            projectTypeEnum = ActProjectTypeEnum.BUSINESS_PURCHASE;
        }
        record.setProjectType(projectTypeEnum.getType());
        record.setTaskDefKey(task.getTaskDefinitionKey());
        record.setTaskName(task.getName());
        record.setTaskComment(comment);
        record.setTaskStatus(status);
        record.setAssigneeId(InterfaceUtil.getAdminId() + "");
        record.setAssigneeName(InterfaceUtil.getAdmin().getRealName());
        record.setTaskIndex(taskIndex);
        record.setCreateTime(new Date());
        return record;
    }

    /**
     * 根据项目id查询审批任务记录
     *
     * @param projectId
     * @param typeEnum
     * @return
     */
    public List<ProjectTaskRecord> listV2(int projectId, ActProjectTypeEnum typeEnum) {
        String select = "tr.*, su.role_name";
        QueryHelper queryHelper = new QueryHelper(select, " project_task_record tr LEFT JOIN sys_user su on su.id=tr.assignee_id  ");
        queryHelper.addCondition("tr.project_id=?", projectId);
        queryHelper.addCondition("tr.project_type=?", typeEnum.getType());
        queryHelper.addOrderProperty("tr.create_time", true);
        return pagination.find(queryHelper.getSql(), ProjectTaskRecord.class);
    }


    /**
     * 根据项目id查询审批任务记录 四算项目使用
     *
     * @param project
     * @return
     */
    public List<ProjectTaskRecord> list(Project project) {
        String select = "tr.*, su.role_name";
        QueryHelper queryHelper = new QueryHelper(select, " project_task_record tr LEFT JOIN sys_user su on su.id=tr.assignee_id  ");
        queryHelper.addCondition("tr.project_id=?", project.getId());
        queryHelper.addCondition("tr.project_type=?", ActProjectTypeEnum.FOURCAL.getType());
        queryHelper.addOrderProperty("tr.create_time", true);
        List<ProjectTaskRecord> projectTaskRecords = pagination.find(queryHelper.getSql(), ProjectTaskRecord.class);

        //设置哪些任务能退回  admin才能退回
        if (!projectTaskRecords.isEmpty() && "admin".equals(InterfaceUtil.getAdmin().getRealName())) {
            //预算流程可能有多个 找到最新的一个预算流程  最新的预算流程才能退回
            String lastProcInsId = "";
            Optional<String> lastProcInsIdOp = projectTaskRecords.stream()
                    .filter(r -> r.getProcDefId().startsWith(ActProcessKeyEnum.BUDGET.getKey()))
                    .map(ProjectTaskRecord::getProcInsId).max(Comparator.naturalOrder());
            if (lastProcInsIdOp.isPresent()) {
                lastProcInsId = lastProcInsIdOp.get();
            }

            int projectStatus = project.getStatus();
            Task currentTask = actUtil.getCurrentTask(project.getId());

            for (ProjectTaskRecord record : projectTaskRecords) {
                if (record.getTaskStatus() == ProjectTaskRecord.STATUS_ROLLBACK) {
                    //已退回记录 不能再退回
                    continue;
                }


                //只能往当前任务之前退回
                StatusEnum statusEnum = StatusEnum.parseByProcDefId(record.getProcDefId());
                if (statusEnum.getStatus() > projectStatus) {
                    //大于当前状态 不能退回
                    continue;
                } else if (statusEnum.getStatus() == projectStatus) {
                    //都在同一个审批里 判断任务节点顺序
                    if (currentTask != null && actUtil.targetBigThanCurrent(record.getProcDefId(),
                            record.getTaskName(), currentTask.getName())) {
                        //如果大于当前节点 不能退回
                        continue;
                    }
                }

                if (!record.getProcDefId().startsWith(ActProcessKeyEnum.BUDGET.getKey())) {
                    //非预算流程全部支持退回
                    record.setCanRollback(true);
                } else {
                    //预算最后一个流程支持退回
                    if (record.getProcInsId().equals(lastProcInsId)) {
                        record.setCanRollback(true);
                    }
                }
            }

        }
        return projectTaskRecords;
    }

}
