package com.yunzhupaas.flowable.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.ImmutableList;
import com.yunzhupaas.exception.WorkFlowException;
import com.yunzhupaas.flowable.entity.*;
import com.yunzhupaas.flowable.enums.NodeEnum;
import com.yunzhupaas.flowable.enums.OperatorStateEnum;
import com.yunzhupaas.flowable.enums.RecordEnum;
import com.yunzhupaas.flowable.enums.TaskStatusEnum;
import com.yunzhupaas.flowable.model.record.ProgressModel;
import com.yunzhupaas.flowable.model.record.RecordVo;
import com.yunzhupaas.flowable.model.record.UserItem;
import com.yunzhupaas.flowable.model.task.FlowMethod;
import com.yunzhupaas.flowable.model.task.FlowModel;
import com.yunzhupaas.flowable.model.templatenode.nodejson.NodeModel;
import com.yunzhupaas.flowable.model.util.FlowNature;
import com.yunzhupaas.flowable.service.NodeRecordService;
import com.yunzhupaas.flowable.service.OperatorService;
import com.yunzhupaas.flowable.service.RecordService;
import com.yunzhupaas.flowable.service.TriggerTaskService;
import com.yunzhupaas.permission.entity.UserEntity;
import com.yunzhupaas.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 类的描述
 *
 * @author YUNZHUPAASYUNZHUPAAS开发组
 * @version 5.0.x
 * @since 2024/4/26 17:05
 */
@Component
public class RecordUtil {
    @Autowired
    private RecordService recordService;
    @Autowired
    private ServiceUtil serviceUtil;
    @Autowired
    private OperatorUtil operatorUtil;
    @Autowired
    private OperatorService operatorService;
    @Autowired
    private NodeRecordService nodeRecordService;
    @Autowired
    private TriggerTaskService triggerTaskService;

    // 根据经办主键获取转审/转办记录
    public RecordEntity getTransferRecord(String operatorId) {
        QueryWrapper<RecordEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(RecordEntity::getOperatorId, operatorId)
                .in(RecordEntity::getHandleType, RecordEnum.transfer.getCode(), RecordEnum.transferProcessing.getCode())
                .orderByDesc(RecordEntity::getHandleTime);
        queryWrapper.lambda().select(RecordEntity::getId, RecordEntity::getHandleId);
        List<RecordEntity> list = recordService.page(new Page<>(1, 1, false), queryWrapper).getRecords();
        if (CollectionUtil.isNotEmpty(list)) {
            return list.get(0);
        }
        return new RecordEntity();
    }

    // 获取节点记录
    public List<NodeRecordEntity> getNodeRecord(String taskId) {
        QueryWrapper<NodeRecordEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(NodeRecordEntity::getTaskId, taskId).ne(NodeRecordEntity::getNodeStatus, 5)
                .orderByDesc(NodeRecordEntity::getCreatorTime);
        List<NodeRecordEntity> list = nodeRecordService.list(queryWrapper);
        return CollectionUtil.isNotEmpty(list) ? list : new ArrayList<>();
    }

    // 根据任务主键、节点id 获取记录
    public List<RecordEntity> getList(String taskId, String nodeId) {
        QueryWrapper<RecordEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(RecordEntity::getTaskId, taskId).eq(RecordEntity::getNodeId, nodeId)
                .orderByDesc(RecordEntity::getHandleTime);
        return recordService.list(wrapper);
    }

    public List<RecordEntity> getList(String taskId) {
        QueryWrapper<RecordEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(RecordEntity::getTaskId, taskId).orderByAsc(RecordEntity::getHandleTime);
        return recordService.list(wrapper);
    }

    public void updateRecords(List<RecordEntity> recordList) {
        if (CollectionUtil.isNotEmpty(recordList)) {
            recordService.updateBatchById(recordList);
        }
    }

    // 将经办相关的记录作废
    public void invalid(List<OperatorEntity> operatorList) {
        List<String> opIds = operatorList.stream().map(OperatorEntity::getId).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(opIds)) {
            QueryWrapper<RecordEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().in(RecordEntity::getOperatorId, opIds);
            List<RecordEntity> list = recordService.list(queryWrapper);
            for (RecordEntity record : list) {
                record.setStatus(-1);
            }
            recordService.updateBatchById(list);
        }
    }

    // 作废加签记录
    public void invalidAddSignRecord(OperatorEntity operator) {
        if (null != operator && null != operator.getId()) {
            QueryWrapper<RecordEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(RecordEntity::getOperatorId, operator.getId()).eq(RecordEntity::getHandleType,
                    RecordEnum.addSign.getCode());
            List<RecordEntity> list = recordService.list(queryWrapper);
            if (CollectionUtil.isNotEmpty(list)) {
                for (RecordEntity record : list) {
                    record.setStatus(-1);
                }
                recordService.updateBatchById(list);
            }
        }
    }

    /**
     * 创建记录
     */
    public void createRecord(FlowMethod flowMethod) {
        FlowModel flowModel = flowMethod.getFlowModel();
        String userId = flowMethod.getUserId();
        OperatorEntity operator = flowMethod.getOperatorEntity();
        Integer type = flowMethod.getType();
        String handId = flowMethod.getHandId();

        // 已存在同意操作的记录（说明是后加签默认同意，无需再次保存）
        if (ObjectUtil.equals(RecordEnum.audit.getCode(), type)) {
            QueryWrapper<RecordEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(RecordEntity::getOperatorId, operator.getId())
                    .eq(RecordEntity::getHandleType, type)
                    .ne(RecordEntity::getStatus, -1);
            if (recordService.count(queryWrapper) > 0)
                return;
        }

        RecordEntity entity = new RecordEntity();
        entity.setId(RandomUtil.uuId());
        entity.setHandleId(handId);
        if (null != operator) {
            if (StringUtil.isBlank(handId)) {
                if (ObjectUtil.equals(operator.getHandleId(), FlowNature.SYSTEM_CODE)) {
                    entity.setHandleId(FlowNature.SYSTEM_CODE);
                } else {
                    entity.setHandleId(operator.getHandleId());
                }
            }
            if (StringUtil.isBlank(entity.getHandleId())) {
                String loginUserId = UserProvider.getLoginUserId();
                entity.setHandleId(loginUserId);
            }
            entity.setNodeId(operator.getNodeId());
            entity.setNodeCode(operator.getNodeCode());
            entity.setNodeName(operator.getNodeName());
            entity.setTaskId(operator.getTaskId());
            entity.setOperatorId(operator.getId());
            entity.setHandleType(operator.getHandleStatus());
            entity.setHandleTime(operator.getHandleTime() == null ? new Date() : operator.getHandleTime());
            entity.setCreatorTime(operator.getCreatorTime() == null ? new Date() : operator.getCreatorTime());
        }
        entity.setHandleOpinion(flowModel.getHandleOpinion());
        entity.setHandleUserId(userId);
        entity.setSignImg(flowModel.getSignImg());
        if (CollectionUtil.isNotEmpty(flowModel.getFileList())) {
            entity.setFileList(JsonUtil.getObjectToString(flowModel.getFileList()));
        }
        // 拓展字段
        List<Map> expandField = flowModel.getApprovalField();
        if (CollectionUtil.isNotEmpty(expandField)) {
            String str = JsonUtil.getObjectToString(expandField);
            entity.setExpandField(str);
        }
        entity.setHandleType(type);
        entity.setStatus(0);

        recordService.save(entity);
    }

    /**
     * 获取流转记录
     *
     * @param records 流转记录集合
     */
    public List<RecordVo> getRecordList(List<RecordEntity> records) {
        List<RecordVo> vos = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(records)) {
            List<UserEntity> userList = serviceUtil
                    .getUserName(records.stream().map(RecordEntity::getHandleId).collect(Collectors.toList()));
            for (RecordEntity record : records) {
                RecordVo vo = JsonUtil.getJsonToBean(record, RecordVo.class);
                UserEntity userEntity = userList.stream().filter(t -> t.getId().equals(record.getHandleId()))
                        .findFirst().orElse(null);
                vo.setUserName(userEntity != null ? userEntity.getRealName() + "/" + userEntity.getAccount() : "");
                if (userEntity != null) {
                    vo.setHeadIcon(UploaderUtil.uploaderImg(userEntity.getHeadIcon()));
                }
                // 设置流转操作人
                String handleUserId = record.getHandleUserId();
                if (StringUtil.isNotEmpty(handleUserId)) {
                    List<String> userIds = Arrays.stream(handleUserId.split(",")).collect(Collectors.toList());
                    List<UserEntity> handleUserList = serviceUtil.getUserName(userIds);
                    List<String> handleUserName = new ArrayList<>();
                    for (String userId : userIds) {
                        UserEntity user = handleUserList.stream().filter(t -> t.getId().equals(userId)).findFirst()
                                .orElse(null);
                        if (null != user) {
                            handleUserName.add(user.getRealName() + "/" + user.getAccount());
                        }
                    }
                    if (CollectionUtil.isNotEmpty(handleUserName)) {
                        vo.setHandleUserName(String.join(",", handleUserName));
                    }
                }
                if (record.getExpandField() != null) {
                    List<Map> expandField = JsonUtil.getJsonToList(record.getExpandField(), Map.class);
                    vo.setApprovalField(expandField);
                }
                vos.add(vo);
            }
        }
        return vos;
    }

    /**
     * 进度
     *
     * @param flowModel 参数
     */
    public List<ProgressModel> getProgressList(FlowModel flowModel) throws WorkFlowException {
        List<ProgressModel> progressList = new ArrayList<>();
        TaskEntity taskEntity = flowModel.getTaskEntity();
        List<TemplateNodeEntity> nodeEntities = flowModel.getNodeEntityList();

        List<NodeRecordEntity> nodeRecordList = nodeRecordService.getList(taskEntity.getId());

        List<OperatorEntity> operatorList = operatorService.getList(taskEntity.getId());
        List<RecordEntity> recordList = recordService.getList(taskEntity.getId());

        List<String> userIds = new ArrayList<>();
        List<String> operatorUserIds = operatorList.stream().map(OperatorEntity::getHandleId)
                .collect(Collectors.toList());
        List<String> recordUserIds = recordList.stream().map(RecordEntity::getHandleId).collect(Collectors.toList());
        userIds.addAll(operatorUserIds);
        userIds.addAll(recordUserIds);
        userIds = userIds.stream().distinct().collect(Collectors.toList());

        List<UserEntity> users = serviceUtil.getUserName(userIds, false);

        for (NodeRecordEntity nodeRecord : nodeRecordList) {

            TemplateNodeEntity nodeEntity = nodeEntities.stream()
                    .filter(e -> e.getNodeCode().equals(nodeRecord.getNodeCode())).findFirst().orElse(null);
            if (null == nodeEntity) {
                continue;
            }
            NodeModel nodeModel = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class);
            if (nodeModel.getType().equals(NodeEnum.subFlow.getType())) {
                continue;
            }
            ProgressModel model = new ProgressModel();
            model.setId(RandomUtil.uuId());
            model.setStartTime(nodeRecord.getCreatorTime().getTime());
            model.setNodeId(nodeRecord.getNodeId());
            model.setNodeCode(nodeRecord.getNodeCode());
            model.setNodeName(nodeRecord.getNodeName());
            model.setNodeType(NodeEnum.approver.getType());
            model.setNodeStatus(nodeRecord.getNodeStatus());
            if (nodeModel.getType().equals(NodeEnum.start.getType())) {
                model.setNodeType(NodeEnum.start.getType());
                progressList.add(model);
                continue;
            }

            model.setCounterSign(nodeModel.getCounterSign());

            List<RecordEntity> records = recordList.stream()
                    .filter(e -> Objects.equals(e.getNodeCode(), nodeModel.getNodeId())
                            && Objects.equals(e.getNodeId(), nodeRecord.getNodeId()))
                    .sorted(Comparator.comparing(RecordEntity::getHandleTime).reversed()).collect(Collectors.toList());

            model.setApproverCount(CollectionUtil.isNotEmpty(records) ? records.size() : 0);

            List<UserItem> items = new ArrayList<>();
            for (int i = 0; i < records.size(); i++) {
                UserItem item = new UserItem();
                RecordEntity record = records.get(i);
                UserEntity user = users.stream().filter(e -> ObjectUtil.equals(record.getHandleId(), e.getId()))
                        .findFirst().orElse(null);
                if (user != null) {
                    item.setHeadIcon(UploaderUtil.uploaderImg(user.getHeadIcon()));
                    item.setUserId(user.getId());
                    item.setUserName(user.getRealName());
                } else {
                    item.setHeadIcon(UploaderUtil.uploaderImg(FlowNature.SYSTEM_HEAD_ICON));
                    item.setUserId(FlowNature.SYSTEM_CODE);
                    item.setUserName(FlowNature.SYSTEM_NAME);
                }
                item.setHandleType(record.getHandleType());
                items.add(item);
                if (i == 3) {
                    break;
                }
            }
            model.setApprover(items);
            // 判断是否存在任务流程
            model.setShowTaskFlow(triggerTaskService.existTriggerTask(taskEntity.getId(), model.getNodeId()));
            progressList.add(model);
        }

        // 当前节点
        List<Integer> status = ImmutableList.of(TaskStatusEnum.RECALL.getCode(), TaskStatusEnum.BACKED.getCode(),
                TaskStatusEnum.CANCEL.getCode());
        if (taskEntity.getEndTime() == null && !status.contains(taskEntity.getStatus())) {
            String currentNodeCode = taskEntity.getCurrentNodeCode();
            if (StringUtil.isNotBlank(currentNodeCode)) {
                List<String> currentCodeList = Arrays.stream(currentNodeCode.split(",")).collect(Collectors.toList());

                for (int i = 0; i < currentCodeList.size(); i++) {
                    String nodeCode = currentCodeList.get(i);

                    TemplateNodeEntity nodeEntity = nodeEntities.stream().filter(e -> e.getNodeCode().equals(nodeCode))
                            .findFirst().orElse(null);
                    if (null == nodeEntity) {
                        continue;
                    }
                    NodeModel nodeModel = JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class);
                    if (nodeModel.getType().equals(NodeEnum.subFlow.getType())) {
                        continue;
                    }
                    boolean isProcessing = ObjectUtil.equals(nodeEntity.getNodeType(), NodeEnum.processing.getType());
                    ProgressModel model = new ProgressModel();
                    model.setId(RandomUtil.uuId());

                    model.setNodeCode(nodeCode);
                    model.setNodeName(nodeModel.getNodeName());
                    model.setNodeType(isProcessing ? NodeEnum.processing.getType() : NodeEnum.approver.getType());
                    model.setNodeStatus(isProcessing ? 8 : 4);
                    model.setCounterSign(nodeModel.getCounterSign());

                    List<OperatorEntity> operators = operatorList.stream()
                            .filter(e -> Objects.equals(e.getNodeCode(), nodeModel.getNodeId())
                                    && !(ObjectUtil.equals(e.getCompletion(), 1) && null == e.getHandleTime()
                                            && !ObjectUtil.equals(e.getParentId(), "0"))
                                    && !Objects.equals(e.getStatus(), OperatorStateEnum.Assist.getCode())
                                    && !Objects.equals(e.getStatus(), OperatorStateEnum.Futility.getCode()))
                            .sorted(Comparator.comparing(OperatorEntity::getCreatorTime, Comparator.reverseOrder())
                                    .thenComparing(OperatorEntity::getCompletion))
                            .collect(Collectors.toList());

                    String nodeId;
                    if (CollectionUtil.isNotEmpty(operators)) {
                        OperatorEntity operator = operators.get(0);
                        nodeId = operator.getNodeId();
                        model.setStartTime(operators.get(0).getCreatorTime().getTime());
                        operators = operators.stream().filter(e -> ObjectUtil.equals(e.getNodeId(), nodeId))
                                .collect(Collectors.toList());
                        // 触发节点选择同步，变更为等待中状态
                        if (ObjectUtil.equals(operator.getStatus(), OperatorStateEnum.Waiting.getCode())) {
                            model.setNodeStatus(7);
                        }
                    } else {
                        nodeId = "";
                    }
                    model.setNodeId(nodeId);
                    model.setApproverCount(CollectionUtil.isNotEmpty(operators) ? operators.size() : 0);

                    List<RecordEntity> records = recordList.stream()
                            .filter(e -> Objects.equals(e.getNodeCode(), nodeModel.getNodeId()))
                            .sorted(Comparator.comparing(RecordEntity::getHandleTime).reversed())
                            .collect(Collectors.toList());

                    List<UserItem> items = new ArrayList<>();
                    for (int j = 0; j < operators.size(); j++) {
                        OperatorEntity operator = operators.get(j);
                        UserItem item = new UserItem();
                        UserEntity user = users.stream()
                                .filter(e -> ObjectUtil.equals(operator.getHandleId(), e.getId())).findFirst()
                                .orElse(null);
                        if (user != null) {
                            item.setHeadIcon(UploaderUtil.uploaderImg(user.getHeadIcon()));
                            item.setUserId(user.getId());
                            item.setUserName(user.getRealName());
                        } else {
                            if (ObjectUtil.equals(operator.getHandleId(), FlowNature.SYSTEM_CODE)) {
                                item.setHeadIcon(FlowNature.SYSTEM_HEAD_ICON);
                                item.setUserName(FlowNature.SYSTEM_NAME);
                                item.setUserId(FlowNature.SYSTEM_CODE);
                            }
                        }

                        if (null != operator.getHandleStatus() && null != operator.getHandleTime()) {
                            item.setHandleType(operator.getHandleStatus());
                        } else {
                            RecordEntity record = records.stream()
                                    .sorted(Comparator.comparing(RecordEntity::getId).reversed())
                                    .filter(e -> ObjectUtil.equals(e.getOperatorId(), operator.getId())
                                            && ObjectUtil.equals(e.getNodeId(), operator.getNodeId())
                                            && !ObjectUtil.equals(e.getStatus(), -1)
                                            && !ObjectUtil.equals(e.getHandleType(), RecordEnum.back.getCode()))
                                    .findFirst().orElse(null);
                            if (null != record) {
                                item.setHandleType(record.getHandleType());
                            } else {
                                // -1.待审 -2.未审 -3.待办理 -4.未办理（暂未用到）
                                item.setHandleType(isProcessing ? -3 : -1);
                            }
                        }
                        items.add(item);
                    }
                    // items =
                    // items.stream().sorted(Comparator.comparing(UserItem::getHandleType)).collect(Collectors.toList());
                    if (items.size() > 4) {
                        items = items.subList(0, 4);
                    }
                    model.setApprover(items);
                    progressList.add(model);
                }
            }
        }

        // 添加结束节点
        if (taskEntity.getEndTime() != null) {
            ProgressModel model = new ProgressModel();
            model.setId(RandomUtil.uuId());
            model.setStartTime(taskEntity.getEndTime().getTime());
            model.setNodeType(NodeEnum.end.getType());
            model.setNodeName("结束");
            progressList.add(model);
        }
        return progressList;
    }
}
