package com.ankaibei.workFlow.webadmin.ankaibei.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ankaibei.workFlow.common.core.object.ResponseResult;
import com.ankaibei.workFlow.common.core.object.TokenData;
import com.ankaibei.workFlow.common.flow.constant.FlowConstant;
import com.ankaibei.workFlow.common.flow.constant.FlowTaskStatus;
import com.ankaibei.workFlow.common.flow.dto.FlowTaskCommentDto;
import com.ankaibei.workFlow.common.flow.model.FlowEntry;
import com.ankaibei.workFlow.common.flow.model.FlowEntryPublish;
import com.ankaibei.workFlow.webadmin.ankaibei.entity.ProjectInfoEntity;
import com.ankaibei.workFlow.webadmin.ankaibei.entity.TaskInfoEntity;
import com.ankaibei.workFlow.webadmin.ankaibei.entity.UserInfoEntity;
import com.ankaibei.workFlow.webadmin.ankaibei.enums.CodeEnum;
import com.ankaibei.workFlow.webadmin.ankaibei.enums.TaskPriority;
import com.ankaibei.workFlow.webadmin.ankaibei.enums.TaskStatus;
import com.ankaibei.workFlow.webadmin.ankaibei.mapper.ProjectInfoMapper;
import com.ankaibei.workFlow.webadmin.ankaibei.mapper.TaskInfoMapper;
import com.ankaibei.workFlow.webadmin.ankaibei.mapper.UserInfoMapper;
import com.ankaibei.workFlow.webadmin.ankaibei.service.TaskInfoService;
import com.ankaibei.workFlow.webadmin.ankaibei.utils.FlowTaskStart;
import com.ankaibei.workFlow.webadmin.ankaibei.vo.ResMsg;
import com.ankaibei.workFlow.webadmin.ankaibei.vo.TaskInfoVo;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lwq
 * @version 1.0
 * @description:
 * @date 2022/9/14 17:19
 */
@Service
public class TaskInfoServiceImpl implements TaskInfoService {

    @Resource
    private TaskInfoMapper taskInfoMapper;
    @Resource
    private UserInfoMapper userInfoMapper;
    @Resource
    private ProjectInfoMapper projectInfoMapper;
    @Autowired
    private FlowTaskStart flowTaskStart;

    @Override
    public ResMsg findTaskInfo(Integer pageIndex, Integer pageSize, TaskInfoEntity taskInfoEntity) {
        Pageable page = PageRequest.of(pageIndex - 1, pageSize);
        Page<Map<String, String>> all = taskInfoMapper.findTaskInfo(taskInfoEntity.getTargetTask(), taskInfoEntity.getTaskStatus(), page);
        //先将项目信息全部查出，再根据项目ID匹配项目名称
        ArrayList<Integer> projectIds = new ArrayList<>();
        ArrayList<String> participants = new ArrayList<>();
        for (Map<String, String> map : all.toList()) {
            projectIds.add(Integer.valueOf(map.get("projectId")));
            participants.add(map.get("taskParticipant"));
        }
        List<ProjectInfoEntity> allById = projectInfoMapper.findAllById(projectIds);
        //先将用户信息全部查出，再根据项目ID匹配项目名称
        HashMap<String, String> userMap = new HashMap<>();
        for (String s : participants) {
            String[] split = s.split(",");
            List<String> list = Arrays.stream(split).collect(Collectors.toList());
            List<UserInfoEntity> allByUserId = userInfoMapper.findAllByUserId(list);
            StringBuffer str = new StringBuffer();
            for (UserInfoEntity name : allByUserId) {
                str.append(name.getShowName()).append(",");
            }
            userMap.put(s, str.toString());
        }

        return new ResMsg(CodeEnum.OK, ResMsg.getMap(all.map(map -> {
            String projectId = map.get("projectId");
            Map<Object, Object> map1 = new HashMap<>();
            map1.putAll(map);

            if (ObjectUtils.isNotEmpty(allById)) {
                for (ProjectInfoEntity infoEntity : allById) {
                    if (projectId.equals(infoEntity.getProjectId() + "")) {
                        map1.put("projectId", infoEntity.getProjectId());
                        map1.put("projectName", infoEntity.getProjectName());
                        continue;
                    }
                }
            }

            String taskParticipant = map.get("taskParticipant");
            if (ObjectUtils.isNotEmpty(userMap)) {
                userMap.entrySet().stream()
                        .forEach(entry -> {
                            if (taskParticipant.equals(entry.getKey())) {
                                map1.put("taskParticipant", entry.getValue());
                                return;
                            }
                        });
            }
            //求任务耗时，结束时间-开始时间
            if (ObjectUtils.isNotEmpty(map1.get("startTime")) && ObjectUtils.isNotEmpty(map1.get("endTime"))) {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
                LocalDateTime startDateTime = LocalDateTime.parse(map1.get("startTime").toString(), formatter);
                LocalDateTime endDateTime = LocalDateTime.parse(map1.get("endTime").toString(), formatter);
                //求差值，转换时间单位
                Duration duration = Duration.between(startDateTime, endDateTime);
                long daysDiff = duration.toDays();
                long hoursDiff = duration.toHours() % 24;
                map1.put("duration_ch", daysDiff + "天" + hoursDiff + "时");
                //任务是否已延期：结束时间已过但是未完成的，就是延期
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                try {
                    if (sdf.parse(map1.get("endTime").toString()).before(new Date()) && !TaskStatus.FINISH_ED.getCode().equals(map1.get("taskStatus").toString())) {
                        if (!TaskStatus.EXTENSION_ED.getCode().equals(map1.get("taskStatus").toString())) {
                            taskInfoMapper.extensionTask(Integer.valueOf(map1.get("taskId").toString()));
                        }
                        map1.put("taskStatus", TaskStatus.EXTENSION_ED.getCode());
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }

            map1.put("taskPriority", TaskPriority.getEnumByCode(map.get("taskPriority")));
            return map1;
        }).getContent(), all.getTotalElements()));
    }

    @Override
    @Transactional
    public ResMsg addTaskInfo(TaskInfoEntity taskInfoEntity, List<Long> taskParticipant) {
        if (taskInfoMapper.countByTargetTaskEqualsAndIsDeleteEquals(taskInfoEntity.getTargetTask(), "1") > 1) {
            return new ResMsg(CodeEnum.TASK_ALREADY_EXISTS);
        }
        if (ObjectUtils.isEmpty(taskInfoEntity.getStartTime()) || ObjectUtils.isEmpty(taskInfoEntity.getEndTime()) || (ObjectUtils.isEmpty(taskInfoEntity.getStartTime()) && ObjectUtils.isEmpty(taskInfoEntity.getEndTime()))) {
            return new ResMsg(CodeEnum.PARAM_IS_NULL, "请录入任务计划的开始时间和结束时间");
        } else {
            //结束时间在此时之前，就已是延期任务
            if (taskInfoEntity.getEndTime().before(new Date())) {
                taskInfoEntity.setTaskStatus(TaskStatus.EXTENSION_ED.getCode());
            }
        }
        if (taskParticipant.size() < 1) {
            //（1 已分配 2未分配 3已延期）
            taskInfoEntity.setTaskStatus(TaskStatus.NO_ALLOCATION.getCode());
        } else {
            taskInfoEntity.setTaskStatus(TaskStatus.ALLOCATION_ED.getCode());
        }
        StringBuffer str = new StringBuffer();
        for (Long id : taskParticipant) {
            str.append(id).append(",");
        }
        taskInfoEntity.setTaskParticipant(str.toString());
        taskInfoEntity.setTaskCreator(taskInfoEntity.getTaskCreator());
        taskInfoEntity.setCreateDate(new Date());
        taskInfoEntity.setIsDelete("1");
        TaskInfoEntity save = taskInfoMapper.save(taskInfoEntity);

        /**
         *调用新增项目任务申请流程的启动
         *获取流程开始节点之后的第一个任务节点的数据
         *param processDefinitionKey 新建项目任务审批流程--流程标识。
         */
        String processDefinitionKey = "projectTaskAddApply";
        ResponseResult<FlowEntry> flowEntryResult = flowTaskStart.verifyAndGetFlowEntry(processDefinitionKey);
        if (!flowEntryResult.isSuccess()) {
            return ResMsg.newInstance(CodeEnum.FAIL, flowEntryResult);
        }
        FlowEntryPublish flowEntryPublish = flowEntryResult.getData().getMainFlowEntryPublish();
        String initTaskInfo = flowEntryPublish.getInitTaskInfo();
        com.ankaibei.workFlow.common.flow.vo.TaskInfoVo taskInfo = StrUtil.isBlank(initTaskInfo)
                ? null : JSON.parseObject(initTaskInfo, com.ankaibei.workFlow.common.flow.vo.TaskInfoVo.class);
        if (ObjectUtils.isNotEmpty(taskInfo)) {
            String loginName = TokenData.takeFromRequest().getLoginName();
            taskInfo.setAssignedMe(StrUtil.equalsAny(
                    taskInfo.getAssignee(), loginName, FlowConstant.START_USER_NAME_VAR));
        }
        //用户在表单页面配置的操作按钮
        FlowTaskCommentDto flowTaskCommentDto = new FlowTaskCommentDto();
        //提交后进行到第二个节点
        flowTaskCommentDto.setApprovalType("agree");
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();
        stringObjectHashMap.put("target_task", taskInfoEntity.getTargetTask());
        stringObjectHashMap.put("task_priority", taskInfoEntity.getTaskPriority());
        stringObjectHashMap.put("task_participant", taskInfoEntity.getTaskParticipant());
        stringObjectHashMap.put("task_plan", taskInfoEntity.getEndTime().toString());
        stringObjectHashMap.put("task_creator", taskInfoEntity.getTaskCreator());
        stringObjectHashMap.put("task_index", taskInfoEntity.getTaskIndex());
        stringObjectHashMap.put("task_standard", taskInfoEntity.getTaskStandard());
        stringObjectHashMap.put("task_statements", taskInfoEntity.getTaskStatements());
        stringObjectHashMap.put("project_id", taskInfoEntity.getProjectId());
        stringObjectHashMap.put("create_date", taskInfoEntity.getCreateDate());
        stringObjectHashMap.put("task_id", save.getTaskId());
        JSONObject masterData = (JSONObject) JSONObject.toJSON(stringObjectHashMap);
        Map<String, String> map = flowTaskStart.startAndTakeUserTaskSS(processDefinitionKey, flowTaskCommentDto, null, masterData, null, null).getData();
        save.setFlowTaskStatus(FlowTaskStatus.SUBMITTED);
        save.setProcessInstanceId(map.get("processInstanceId"));
        save.setProcessDefinitionId(map.get("processDefinitionId"));
        taskInfoMapper.save(save);
        return new ResMsg(CodeEnum.OK);
    }

    @Override
    public ResMsg deleteTask(List<TaskInfoVo> taskInfoVos) {
        //   //审批状态   已提交：0; 审批中：1; 被拒绝：2; 已结束：3; 提前停止：4; 已取消：5;
        StringBuffer optional = new StringBuffer("任务：[");
        int count = 0;
        for (TaskInfoVo info : taskInfoVos) {
            TaskInfoEntity byId = taskInfoMapper.getById(info.getTaskId());
            if (byId.getFlowTaskStatus() > 1) {
                taskInfoMapper.deleteTask(info.getTaskId());
                count++;
            } else {
                optional.append(byId.getTargetTask() + ",");
            }
        }
        optional.replace(optional.length() - 1, optional.length(), "");
        optional.append("] 审批未结束，不可删除！");
        if (count == taskInfoVos.size()) {
            return new ResMsg(CodeEnum.OK, "");
        } else {
            return new ResMsg(CodeEnum.FAIL, optional);
        }
    }

    @Override
    public ResMsg findTaskById(TaskInfoVo taskInfoVo) {
        Optional<TaskInfoEntity> byId = taskInfoMapper.findById(taskInfoVo.getTaskId());
        if (ObjectUtils.isEmpty(byId)) {
            return new ResMsg(CodeEnum.NO_DATA);
        }
        //任务发起人
        byId.get().setTaskCreator(userInfoMapper.getById(byId.get().getTaskCreator()).getShowName());

        return new ResMsg(CodeEnum.OK, byId.orElse(null));
    }

    @Override
    public ResMsg performTask(TaskInfoEntity taskInfoEntity) {
        if (taskInfoMapper.performTask(taskInfoEntity.getTaskId()) < 1) {
            return new ResMsg(CodeEnum.FAIL);
        }
        return new ResMsg(CodeEnum.OK);
    }
}
