package com.hotent.project.manager.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hotent.base.util.StringUtil;
import com.hotent.constant.NodeConstant;
import com.hotent.project.manager.*;
import com.hotent.project.model.CostProjectMaterial;
import com.hotent.project.model.CostProjectProccess;
import com.hotent.project.dao.CostProjectProccessDao;
import com.hotent.base.manager.impl.BaseManagerImpl;
import com.hotent.project.model.CostProjectProccessNode;
import com.hotent.project.model.CostProjectProccessNodeTemplete;
import com.hotent.project.req.CostProjectProcessNodeReq;
import com.hotent.project.req.CostProjectProcessReq;
import com.hotent.project.resp.CostProjectProccessNodeResp;
import com.hotent.project.resp.CostProjectProccessResp;
import com.hotent.sys.persistence.manager.DataDictManager;
import com.hotent.sys.persistence.model.DataDict;
import com.hotent.uc.exception.BaseException;
import com.hotent.uc.manager.UserManager;
import com.hotent.uc.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;


/**
 * 流程表 服务实现类
 *
 * @author 超级管理员0
 * @company 山西清众科技股份有限公司
 * @since 2025-10-01
 */
@Service
public class CostProjectProccessManagerImpl extends BaseManagerImpl<CostProjectProccessDao, CostProjectProccess> implements CostProjectProccessManager {


    @Autowired
    private CostProjectProccessNodeTempleteManager costProjectProccessNodeTempleteManager;


    @Autowired
    private CostProjectProccessNodeManager costProjectProccessNodeManager;


    @Resource
    DataDictManager dataDictManager;

    @Autowired
    private CostProjectProccessPersonnelManager costProjectProccessPersonnelManager;


    @Autowired
    private UserManager userManager;


    @Override
    public CostProjectProccessResp getDetail(String id) {


        //获取流程
        LambdaQueryWrapper<CostProjectProccess> qw = new LambdaQueryWrapper<>();
        qw.eq(CostProjectProccess::getProjectId, id);
        CostProjectProccess projectProccess = this.getOne(qw, false);
        if (projectProccess == null) {
            return new CostProjectProccessResp();
        }


        //获取流程节点
        LambdaQueryWrapper<CostProjectProccessNode> qwNode = new LambdaQueryWrapper<>();
        qwNode.eq(CostProjectProccessNode::getProcessId, projectProccess.getProcessId());
        List<CostProjectProccessNode> nodeList = costProjectProccessNodeManager.list(qwNode);


        List<String> userIdList = new ArrayList<>();

        nodeList.stream().forEach(node -> {
            if (!ObjectUtil.isEmpty(node.getMainUserId())) {
                userIdList.add(node.getMainUserId());
            }
            if (!ObjectUtil.isEmpty(node.getUserId())) {
                if (node.getUserId().contains(",")) {
                    String[] split = node.getUserId().split(",");
                    userIdList.addAll(Arrays.asList(split));
                } else {
                    userIdList.add(node.getUserId());
                }
            }

        });
        if (ObjectUtil.isEmpty(userIdList)) {
            throw new BaseException("未找到流程节点人员");
        }
        //获取流程节点人员名称
        List<User> users = userManager.listByIds(userIdList.stream().distinct().collect(Collectors.toList()));
        Map<String, User> userMap = users.stream().collect(Collectors.toMap(User::getId, Function.identity()));

        //List<String> listRequire = records.stream().map(CostProjectMaterial::getInformationRequire).distinct().collect(Collectors.toList());
        List<String> nodeTypes = nodeList.stream().map(CostProjectProccessNode::getNodeType).distinct().collect(Collectors.toList());
        QueryWrapper<DataDict> wrapperRequire = new QueryWrapper<>();
        wrapperRequire.eq("TYPE_ID_","1976857973275787264");
        wrapperRequire.in("KEY_",nodeTypes);
        List<DataDict> listnodeType= dataDictManager.list(wrapperRequire);

        List<String> listStatus = nodeList.stream().map(CostProjectProccessNode::getStatus).collect(Collectors.toList());
        List<String> result = listStatus.stream()
                .flatMap(str -> Arrays.stream(str.split(",")))
                .map(String::trim)
                .filter(s -> !s.isEmpty())
                .distinct()
                .collect(Collectors.toList());

        QueryWrapper<DataDict> wrapperStatus = new QueryWrapper<>();
        wrapperStatus.eq("TYPE_ID_","1977549156280991744");
        wrapperStatus.in("KEY_",result);
        List<DataDict> listnodeStatus= dataDictManager.list(wrapperStatus);


        //返回流程数据
        CostProjectProccessResp costProjectProccessResp = new CostProjectProccessResp();

        costProjectProccessResp.setProjectId(projectProccess.getProjectId());
        costProjectProccessResp.setProcessId(projectProccess.getProcessId());
        costProjectProccessResp.setPlannedAuditStartDate(projectProccess.getPlannedAuditStartDate());
        costProjectProccessResp.setPlannedAuditEndDate(projectProccess.getPlannedAuditEndDate());




        costProjectProccessResp.setNodeList(nodeList.stream().map(node -> {
            CostProjectProccessNodeResp nodeResp = new CostProjectProccessNodeResp();
            nodeResp.setId(node.getId());

            nodeResp.setProcessId(node.getProcessId());
            nodeResp.setProcessNodeValue(node.getProcessNodeValue());
            nodeResp.setProcessNodeKey(node.getProcessNodeKey());
            nodeResp.setNodeType(node.getNodeType());

            listnodeType.stream()
                    .filter(c -> nodeResp.getNodeType() != null &&
                            nodeResp.getNodeType().equals(String.valueOf(c.getKey())))
                    .findAny().ifPresent(costDictData -> nodeResp.setNodeTypeName(costDictData.getName()));


            nodeResp.setOrderNum(node.getOrderNum());
            nodeResp.setStatus(node.getStatus());
            if (StringUtil.isNotEmpty(nodeResp.getStatus())) {
                String[] split = nodeResp.getStatus().split(",");
                StringBuilder statusName= new StringBuilder();
                for (int i = 0; i < split.length; i++) {
                    String st=split[i];
                    DataDict dataDict = listnodeStatus.stream().filter(s -> s.getKey().equals(st)).findAny().orElse(null);
                    if (dataDict!=null) {
                        if(i == 0){
                            statusName.append(dataDict.getName());
                        }else {
                            statusName.append(",").append(dataDict.getName());
                        }

                    }
                }
                nodeResp.setStatusName(statusName.toString());
            }

            nodeResp.setUserId(node.getUserId());
            nodeResp.setMainUserId(node.getMainUserId());
            nodeResp.setStatusValue("node.getStatusValue() 后面填写");
            if("1".equals(node.getNodeType())) {
                nodeResp.setMainUserName(userMap.get(node.getMainUserId()).getFullname());
                if (node.getUserId().contains(",")) {
                    String[] userIds = node.getUserId().split(",");
                    String userName = "";
                    for (String userId : userIds) {
                        User user = userMap.get(userId);
                        userName = userName + user.getFullname() + ",";
                    }
                    nodeResp.setUserName(userName.substring(0, userName.length() - 1));
                } else {
                    nodeResp.setUserName(userMap.get(node.getUserId()).getFullname());
                }
            }
            nodeResp.setEndTime(node.getEndTime());
            nodeResp.setStartTime(node.getStartTime());
            nodeResp.setActEndTime(node.getActEndTime());
            nodeResp.setActStartTime(node.getActStartTime());
            nodeResp.setActRemarks(node.getActRemarks());
            nodeResp.setActUserNames(node.getActUserNames());




            return nodeResp;
        }).collect(Collectors.toList()));

        return costProjectProccessResp;
    }

    @Override
    @Transactional
    public void createOrUpdate(CostProjectProccess costProjectProccess) {
        //新建或更新
        this.saveOrUpdate(costProjectProccess);
    }

    @Override
    @Transactional
    public void createProcess(CostProjectProcessReq req) {

        for (CostProjectProcessNodeReq nodeReq : req.getNodeReqList()) {
            if ("1".equals(nodeReq.getNodeType())) {
                if (req.getPlannedAuditEndDate().isBefore(nodeReq.getEndTime())) {
                    throw new BaseException("流程节点的结束时间不能早于流程的结束时间");
                }
                if (ObjectUtil.isEmpty(nodeReq.getUserId())) {
                    throw new BaseException("流程节点人员不能为空");
                }
                if (ObjectUtil.isEmpty(nodeReq.getMainUserId())) {
                    throw new BaseException("流程节点主办人员不能为空");
                }
                if (ObjectUtil.isEmpty(nodeReq.getProcessNodeKey())) {
                    throw new BaseException("流程环节实际值不能为空");
                }
                if (ObjectUtil.isEmpty(nodeReq.getStatus())) {
                    throw new BaseException("流程节点流转操作不能为空");
                }
            }
        }
        LambdaQueryWrapper<CostProjectProccess> qw = new LambdaQueryWrapper<>();
        qw.eq(CostProjectProccess::getProjectId, req.getProjectId());
        CostProjectProccess one = this.getOne(qw);

        if(one != null) {
            this.remove(qw);
            LambdaQueryWrapper<CostProjectProccessNode> qwNode = new LambdaQueryWrapper<>();
            qwNode.eq(CostProjectProccessNode::getProcessId, one.getProcessId());
        }

        //新增流程
        CostProjectProccess costProjectProccess = new CostProjectProccess();
        if (ObjectUtil.isNotEmpty(req.getProcessId())) {
            req.setProcessId(req.getProcessId());
        }
        costProjectProccess.setProjectId(req.getProjectId());
        costProjectProccess.setPlannedAuditStartDate(req.getPlannedAuditStartDate());
        costProjectProccess.setPlannedAuditEndDate(req.getPlannedAuditEndDate());
        costProjectProccess.setStatus(1);
        costProjectProccess.setCurrentNode(NodeConstant.clcs.getNodeKey());
        costProjectProccess.setProccessTempleteId("1");
        this.saveOrUpdate(costProjectProccess);


        //获取流程节点
        List<CostProjectProccessNodeTemplete> nodeList = costProjectProccessNodeTempleteManager.list();
        if (req.getNodeReqList().size() != nodeList.size()) {
            throw new BaseException("流程节点数量不一致");
        }
        Map<String, CostProjectProcessNodeReq> nodeReqMap = req.getNodeReqList().stream().collect(Collectors.toMap(CostProjectProcessNodeReq::getProcessNodeKey, Function.identity()));


        List<CostProjectProccessNode> nodes = new ArrayList<>();
        for (CostProjectProccessNodeTemplete nodeTemplete : nodeList) {
            CostProjectProcessNodeReq nodeReq = nodeReqMap.get(nodeTemplete.getProcessNodeKey());
            if (nodeReq == null) {
                throw new BaseException("未找到节点配置: " + nodeTemplete.getProcessNodeKey());
            }

            CostProjectProccessNode costProjectProccessNode = getCostProjectProccessNode(nodeTemplete, costProjectProccess, nodeReq);
            nodes.add(costProjectProccessNode);
        }
        costProjectProccessNodeManager.saveOrUpdateBatch(nodes);

//            Map<String, CostProjectProccessNode> proccessNodeMap = nodes.stream().collect(Collectors.toMap(CostProjectProccessNode::getProcessNodeKey, Function.identity()));
//            Map<String, List<CostProjectProccessPersonnel>> personMap = persons.stream().collect(Collectors.groupingBy(CostProjectProccessPersonnel::getNodeId));

//            personMap.forEach((nodeId, personList) -> {
//                CostProjectProccessNode node = proccessNodeMap.get(nodeId);
//                personList.forEach(person -> {
//                    person.setNodeId(node.getId());
//                });
//            });
//            costProjectProccessPersonnelManager.saveOrUpdateBatch(persons);
//            System.out.println(JSON.toJSONString(persons));
    }

    @Override
    public CostProjectProccess getProcessByProjectId(String projectId) {
        LambdaQueryWrapper<CostProjectProccess> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CostProjectProccess::getProjectId, projectId);
        CostProjectProccess one = this.getOne(queryWrapper, false);
        if (one == null) {
            return new CostProjectProccess();
        }
        return one;
    }

    private static CostProjectProccessNode getCostProjectProccessNode(CostProjectProccessNodeTemplete
                                                                              nodeTemplete, CostProjectProccess costProjectProccess, CostProjectProcessNodeReq nodeReq) {
        CostProjectProccessNode costProjectProccessNode = new CostProjectProccessNode();
        costProjectProccessNode.setProcessId(costProjectProccess.getProcessId());
        costProjectProccessNode.setMainUserId(nodeReq.getMainUserId());
        costProjectProccessNode.setUserId(nodeReq.getUserId());
        costProjectProccessNode.setProcessNodeValue(nodeTemplete.getProcessNodeValue());
        costProjectProccessNode.setProcessNodeKey(nodeReq.getProcessNodeKey());
        costProjectProccessNode.setNodeType(nodeTemplete.getNodeType());
        costProjectProccessNode.setOrderNum(nodeTemplete.getOrderNum());
        costProjectProccessNode.setEndTime(nodeReq.getEndTime());
        costProjectProccessNode.setStartTime(costProjectProccess.getPlannedAuditStartDate());
        costProjectProccessNode.setStatus(nodeReq.getStatus());
        return costProjectProccessNode;
    }
}


