package com.fs.company.service.impl;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fs.common.exception.CustomException;
import com.fs.common.utils.StringUtils;
import com.fs.company.domain.CompanyAiWorkflowExec;
import com.fs.company.domain.CompanyAiWorkflowExecLog;
import com.fs.company.domain.CompanyWorkflow;
import com.fs.company.domain.CompanyWorkflowNode;
import com.fs.company.mapper.CompanyAiWorkflowExecLogMapper;
import com.fs.company.mapper.CompanyAiWorkflowExecMapper;
import com.fs.company.mapper.CompanyWorkflowMapper;
import com.fs.company.mapper.CompanyWorkflowNodeMapper;
import com.fs.company.param.ExecutionContext;
import com.fs.company.service.CompanyWorkflowEngine;
import com.fs.company.service.IWorkflowNode;
import com.fs.company.service.impl.call.node.WorkflowNodeFactory;
import com.fs.company.vo.ExecutionResult;
import com.fs.enums.ExecutionStatusEnum;
import com.fs.enums.NodeTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;

/**
 * @author MixLiu
 * @date 2026/1/28 14:22
 * @description
 */
@Service
@Slf4j
public class CompanyWorkflowEngineImpl implements CompanyWorkflowEngine {

    @Autowired
    private WorkflowNodeFactory nodeFactory;

    @Autowired
    private CompanyAiWorkflowExecMapper currentExecutionMapper;

    @Autowired
    private CompanyAiWorkflowExecLogMapper executionLogMapper;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private CompanyWorkflowMapper companyWorkflowMapper;

    @Autowired
    private CompanyWorkflowNodeMapper companyWorkflowNodeMapper;

    @Autowired
    private CompanyAiWorkflowExecLogMapper companyAiWorkflowExecLogMapper;

    /**
     * 初始化工作流
     * 创建工作流实例并保存初始状态
     */
    @Override
    public ExecutionResult initialize(Long workflowDefinitionId, Map<String, Object> inputVariables) {
        try {
            if(!inputVariables.containsKey("cidGroupNo")){
                throw new CustomException("参数错误：未指定cidGroupNo");
            }
            // 生成工作流实例ID
            String workflowInstanceId = generateInstanceId();

            // 加载工作流定义
            CompanyWorkflow definition = loadCompanyWorkflow(workflowDefinitionId);

            // 创建执行上下文
            ExecutionContext context = createContext(workflowInstanceId, inputVariables);

            // 保存当前执行记录
            saveInitialExecution(workflowInstanceId, workflowDefinitionId,
                    definition.getStartNodeKey(), context, definition);

            log.info("工作流初始化成功: {} -> {}", workflowInstanceId, workflowDefinitionId);

            return ExecutionResult.success()
                    .nextNodeKey(definition.getStartNodeKey())
                    .workflowInstanceId(workflowInstanceId).build();

        } catch (Exception e) {
            log.error("工作流初始化失败: {}", workflowDefinitionId, e);
            return ExecutionResult.failure()
                    .errorMessage("Initialization failed: " + e.getMessage()).build();
        }
    }

    /**
     * 执行指定节点
     * 根据节点ID执行对应的节点逻辑
     */
    @Override
    @Async("cidWorkFlowExecutor")
    public void executeNode(String workflowInstanceId, String nodeKey) {
        try {
            // 加载当前执行记录
            CompanyAiWorkflowExec currentExec =
                    currentExecutionMapper.selectByWorkflowInstanceId(workflowInstanceId);

            if (currentExec == null) {
                throw new CustomException("工作流实例不存在: " + workflowInstanceId);
            }

            // 反序列化执行上下文
            ExecutionContext context = deserializeContext(currentExec);

            // 加载工作流定义
            CompanyWorkflow definition = loadCompanyWorkflow(
                    currentExec.getWorkflowId());

            // 创建节点实例并执行
            IWorkflowNode node = createNode(definition, nodeKey);
            if (node == null) {
                throw new CustomException("节点不存在: " + nodeKey);
            }

            // 更新当前节点到执行上下文
            context.setCurrentNodeKey(nodeKey);
            ExecutionResult result = node.execute(context);

            // 处理执行结果
//            if (ExecutionStatusEnum.SUCCESS.equals(result.getStatus())) {
//                // 检查是否是结束节点或无下一节点
//                if (StringUtils.isBlank(result.getNextNodeKey())) {
//                    // 结束工作流
//                    completeWorkflow(workflowInstanceId);
//                    log.info("工作流执行完成 - workflowInstanceId: {}", workflowInstanceId);
//                } else {
//                    // 继续执行下一个节点
//                    executeNode(workflowInstanceId, result.getNextNodeKey());
//                }
//            } else if(ExecutionStatusEnum.FAILURE.equals(result.getStatus())) {
//                // 执行失败时更新状态
//                updateWorkflowStatus(workflowInstanceId, ExecutionStatusEnum.FAILURE);
//                log.error("节点执行失败 - workflowInstanceId: {}, nodeKey: {}, error: {}",
//                        workflowInstanceId, nodeKey, result.getErrorMessage());
//            }
        } catch (Exception e) {
            log.error("节点执行异常: {} -> {}", workflowInstanceId, nodeKey, e);
            updateWorkflowStatus(workflowInstanceId, ExecutionStatusEnum.FAILURE);
            throw new CustomException("节点执行失败: " + e.getMessage());
        }
    }

    /**
     * 暂停工作流
     * 将工作流状态设置为暂停
     */
    @Override
    public ExecutionResult pauseWorkflow(String workflowInstanceId) {
        try {
            CompanyAiWorkflowExec update = new CompanyAiWorkflowExec();
            update.setWorkflowInstanceId(workflowInstanceId);
            update.setStatus(ExecutionStatusEnum.PAUSED.getValue());
            update.setLastUpdateTime(LocalDateTime.now());

            int rows = currentExecutionMapper.updateByWorkflowInstanceId(update);

            if (rows > 0) {
                log.info("工作流暂停成功: {}", workflowInstanceId);
                return ExecutionResult.success().build();
            } else {
                return ExecutionResult.failure()
                        .errorMessage("工作流实例不存在: " + workflowInstanceId).build();
            }

        } catch (Exception e) {
            log.error("暂停工作流失败: {}", workflowInstanceId, e);
            return ExecutionResult.failure()
                    .errorMessage("Pause failed: " + e.getMessage()).build();
        }
    }

    /**
     * 结束工作流
     * 将工作流状态设置为完成
     */
    @Override
    public ExecutionResult completeWorkflow(String workflowInstanceId) {
        try {
            CompanyAiWorkflowExec update = new CompanyAiWorkflowExec();
            update.setWorkflowInstanceId(workflowInstanceId);
            update.setStatus(ExecutionStatusEnum.SUCCESS.getValue());
            update.setLastUpdateTime(LocalDateTime.now());

            int rows = currentExecutionMapper.updateByWorkflowInstanceId(update);

            if (rows > 0) {
                log.info("工作流结束成功: {}", workflowInstanceId);
                return ExecutionResult.success().build();
            } else {
                return ExecutionResult.failure()
                        .errorMessage("工作流实例不存在: " + workflowInstanceId).build();
            }

        } catch (Exception e) {
            log.error("结束工作流失败: {}", workflowInstanceId, e);
            return ExecutionResult.failure()
                    .errorMessage("Complete failed: " + e.getMessage()).build();
        }
    }

    /**
     * 记录执行日志
     * 保存节点执行的相关信息
     */
    @Override
    public void logExecution(CompanyAiWorkflowExecLog logEntry) {
        try {
            CompanyAiWorkflowExecLog logRecord = new CompanyAiWorkflowExecLog();
            logRecord.setWorkflowInstanceId(logEntry.getWorkflowInstanceId());
            logRecord.setNodeId(logEntry.getNodeId());
            logRecord.setNodeType(logEntry.getNodeType());
            logRecord.setStatus(logEntry.getStatus());
            logRecord.setInputData(objectMapper.writeValueAsString(logEntry.getInputData()));
            logRecord.setOutputData(objectMapper.writeValueAsString(logEntry.getOutputData()));
            logRecord.setStartTime(logEntry.getStartTime());
            logRecord.setEndTime(logEntry.getEndTime());
            logRecord.setErrorMessage(logEntry.getErrorMessage());
            logRecord.setDuration(logEntry.getDuration());

            executionLogMapper.insert(logRecord);

        } catch (Exception e) {
            log.error("记录执行日志失败", e);
        }
    }

    /**
     * 创建日志记录对象
     */
    private CompanyAiWorkflowExecLog createLogEntry(String workflowInstanceId, String nodeKey,
                                                    NodeTypeEnum nodeType, ExecutionResult result) {

        try {
            CompanyAiWorkflowExecLog logEntry = new CompanyAiWorkflowExecLog();
            logEntry.setWorkflowInstanceId(workflowInstanceId);
            logEntry.setNodeKey(nodeKey);
            logEntry.setNodeType(nodeType.getValue());
            logEntry.setStatus(result.getStatus().getValue());

            logEntry.setOutputData(objectMapper.writeValueAsString(result.getOutputData()));
            logEntry.setErrorMessage(result.getErrorMessage());
            logEntry.setStartTime(new Date());
            logEntry.setEndTime(new Date());
            logEntry.setDuration(0L); // 可以根据实际情况计算持续时间

            return logEntry;
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 保存初始执行记录
     */
    private void saveInitialExecution(String workflowInstanceId, Long workflowDefinitionId,
                                      String startNodeKey, ExecutionContext context, CompanyWorkflow workflow) {

        try {
            CompanyAiWorkflowExec currentExec = new CompanyAiWorkflowExec();
            currentExec.setWorkflowInstanceId(workflowInstanceId);
            currentExec.setWorkflowId(workflowDefinitionId);
            currentExec.setCurrentNodeKey(startNodeKey);
            currentExec.setCurrentNodeType(NodeTypeEnum.START.getValue());
            currentExec.setCurrentNodeName(NodeTypeEnum.START.getDescription());
            currentExec.setStatus(ExecutionStatusEnum.READY.getValue());
            currentExec.setStartTime(LocalDateTime.now());
            currentExec.setVariables(objectMapper.writeValueAsString(context.getVariables()));
            // 如果有业务键
            currentExec.setBusinessKey(context.getBusinessId());
            currentExec.setStartNodeKey(workflow.getStartNodeKey());
            currentExec.setEndNodeKey(workflow.getEndNodeKey());
            currentExec.setCidGroupNo(context.getVariable("cidGroupNo",Integer.class));
            currentExec.setRuntimeRangeStart(context.getVariable("runtimeRangeStart", LocalTime.class));
            currentExec.setRuntimeRangeEnd(context.getVariable("runtimeRangeEnd",LocalTime.class));
            currentExecutionMapper.insert(currentExec);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 更新当前执行记录
     */
    private void updateCurrentExecution(String workflowInstanceId, String currentNodeKey,
                                        ExecutionContext context) {
        try {
            CompanyAiWorkflowExec update = new CompanyAiWorkflowExec();
            update.setWorkflowInstanceId(workflowInstanceId);
            update.setCurrentNodeKey(currentNodeKey);

            update.setVariables(objectMapper.writeValueAsString(context.getVariables()));
            update.setLastUpdateTime(LocalDateTime.now());

            currentExecutionMapper.updateByWorkflowInstanceId(update);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 更新当前节点
     */
    private void updateCurrentNode(String workflowInstanceId, String nextNodeKey) {
        CompanyAiWorkflowExec update = new CompanyAiWorkflowExec();
        update.setWorkflowInstanceId(workflowInstanceId);
        update.setCurrentNodeKey(nextNodeKey);
        update.setLastUpdateTime(LocalDateTime.now());
        currentExecutionMapper.updateCompanyAiWorkflowExec(update);
    }

    /**
     * 更新工作流状态
     */
    private void updateWorkflowStatus(String workflowInstanceId, ExecutionStatusEnum status) {
        CompanyAiWorkflowExec update = new CompanyAiWorkflowExec();
        update.setWorkflowInstanceId(workflowInstanceId);
        update.setStatus(status.getValue());
        update.setLastUpdateTime(LocalDateTime.now());
        currentExecutionMapper.updateByWorkflowInstanceId(update);
    }

    /**
     * 创建节点实例
     */
    private IWorkflowNode createNode(CompanyWorkflow definition, String nodeKey) {
        CompanyWorkflowNode node = companyWorkflowNodeMapper.selectNodeByWorkflowIdAndNodeKey(definition.getWorkflowId(), nodeKey);
        if (node == null) {
            return null;
        }
        return nodeFactory.createNode(
                node.getNodeKey(),
                NodeTypeEnum.fromCode(node.getNodeType()),
                node.getNodeName(),
                JSON.parseObject(node.getNodeConfig(), Map.class));
    }

    /**
     * 生成工作流实例ID
     */
    private String generateInstanceId() {
        return "wf_" + System.currentTimeMillis() + "_" +
                UUID.randomUUID().toString().replace("-", "");
    }

    /**
     * 创建执行上下文
     */
    private ExecutionContext createContext(String workflowInstanceId,
                                           Map<String, Object> inputVariables) {
        ExecutionContext context = new ExecutionContext();
        context.setWorkflowInstanceId(workflowInstanceId);
        context.setVariables(inputVariables != null ? inputVariables : new HashMap<>());
        context.setStartTime(LocalDateTime.now());
        context.setCurrentTime(LocalDateTime.now());
        context.setBusinessId(inputVariables.containsKey("businessId") ? Long.parseLong(inputVariables.get("businessId").toString()) : null);

        return context;
    }

    /**
     * 反序列化执行上下文
     */
    private ExecutionContext deserializeContext(CompanyAiWorkflowExec record) {
        ExecutionContext context = new ExecutionContext();
        context.setWorkflowInstanceId(record.getWorkflowInstanceId());
        context.setCurrentNodeKey(record.getCurrentNodeKey());
        context.setStartTime(record.getStartTime());
        context.setCurrentTime(LocalDateTime.now());
        context.setBusinessId(record.getBusinessKey());
        try {
            if (StringUtils.isNotBlank(record.getVariables())) {
                Map<String, Object> variables = objectMapper.readValue(
                        record.getVariables(), Map.class);
                context.setVariables(variables);
            }
        } catch (Exception e) {
            log.error("反序列化上下文变量失败", e);
        }

        return context;
    }

    /**
     * 加载工作流定义
     */
    private CompanyWorkflow loadCompanyWorkflow(Long id) {
        // 实现根据ID加载工作流定义的逻辑
        return companyWorkflowMapper.selectCompanyWorkflowById(id);
    }

    //    /**
//     * 将工作流设置为阻塞状态
//     */
//    private void pauseWorkflowForBlockingNode(String workflowInstanceId, String nodeKey, ExecutionContext context) {
//        try {
//            CompanyAiWorkflowExec update = new CompanyAiWorkflowExec();
//            update.setWorkflowInstanceId(workflowInstanceId);
//            update.setStatus(ExecutionStatusEnum.WAITING.getValue());
//            update.setLastUpdateTime(LocalDateTime.now());
//            update.setVariables(objectMapper.writeValueAsString(context.getVariables()));
//
//            currentExecutionMapper.updateByWorkflowInstanceId(update);
//            log.info("工作流已阻塞在节点: {} -> {}", workflowInstanceId, nodeKey);
//        } catch (Exception e) {
//            log.error("更新工作流阻塞状态失败: {}", workflowInstanceId, e);
//        }
//    }
    @Override
    public void resumeFromBlockingNode(String workflowInstanceId, String nodeKey, Map<String, Object> inputData) {
        try {
            // 加载当前执行记录
            CompanyAiWorkflowExec currentExec = currentExecutionMapper.selectByWorkflowInstanceId(workflowInstanceId);

            if (currentExec == null) {
                throw new CustomException("工作流实例不存在: " + workflowInstanceId);
            }

            // 验证当前节点是否匹配
            if (!nodeKey.equals(currentExec.getCurrentNodeKey())) {
                log.warn("节点不匹配 - 期望: {}, 实际: {}", nodeKey, currentExec.getCurrentNodeKey());
                throw new CustomException("节点不匹配，期望: " + nodeKey + ", 实际: " + currentExec.getCurrentNodeKey());
            }

            // 检查当前工作流是否处于暂停状态
            if (!Integer.valueOf(ExecutionStatusEnum.PAUSED.getValue()).equals(currentExec.getStatus()) &&
                !Integer.valueOf(ExecutionStatusEnum.WAITING.getValue()).equals(currentExec.getStatus())) {
                throw new CustomException("工作流未处于暂停状态，无法唤醒: " + workflowInstanceId);
            }

            // 反序列化执行上下文并合并新的输入数据
            ExecutionContext context = deserializeContext(currentExec);
            if (inputData != null) {
                context.getVariables().putAll(inputData);
            }

            // 加载工作流定义
            CompanyWorkflow definition = loadCompanyWorkflow(currentExec.getWorkflowId());

            // 创建节点实例
            IWorkflowNode node = createNode(definition, nodeKey);
            if (node == null) {
                throw new CustomException("节点不存在: " + nodeKey);
            }

            // 继续执行节点逻辑
            ExecutionResult result = node.continueExecute(context);

        } catch (Exception e) {
            log.error("唤醒阻塞节点失败: {} -> {}", workflowInstanceId, nodeKey, e);
//            updateWorkflowStatus(workflowInstanceId, ExecutionStatusEnum.FAILURE);
            throw new CustomException("Resume from blocking node failed: " + e.getMessage());
        }
    }

    /**
     * 定时任务 唤醒执行工作流节点
     *
     * @param workflowInstanceId
     * @param nodeKey
     * @param inputData
     */
    @Override
    public void timeDoExecute(String workflowInstanceId, String nodeKey, Map<String, Object> inputData) {
        try {
            // 加载当前执行记录
            CompanyAiWorkflowExec currentExec = currentExecutionMapper.selectByWorkflowInstanceId(workflowInstanceId);

            if (currentExec == null) {
                throw new CustomException("工作流实例不存在: " + workflowInstanceId);
            }
            String execNode = currentExec.getCurrentNodeKey();

            if (null == inputData || !inputData.containsKey("lastNodeKey")) {
                throw new CustomException("节点流程匹配有误: " + inputData);
            }
            String lastNodeKey = (String) inputData.get("lastNodeKey");

            // 验证节点是否匹配
            if (!lastNodeKey.equals(execNode)) {
                log.error("当前流程已扭转节点不匹配 - 期望: {}, 实际: {}", lastNodeKey, execNode);
                throw new CustomException("节点不匹配，期望: " + lastNodeKey + ", 实际: " + execNode);
            }
            if (!inputData.containsKey("callSource")) {
                throw new CustomException("未声明调用来源: " + inputData + "::" + workflowInstanceId);
            }
            String cs = (String) inputData.get("callSource");
            // 上个节点阻塞校验
            if (("callTaskTimer".equals(cs) && !Integer.valueOf(ExecutionStatusEnum.WAITING.getValue()).equals(currentExec.getStatus())) ||
                    (("addWxTimer".equals(cs) && !Integer.valueOf(ExecutionStatusEnum.WAITING.getValue()).equals(currentExec.getStatus())))) {
                throw new CustomException("工作流未处于暂停状态，无法唤醒: " + workflowInstanceId);
            }
            // 反序列化执行上下文并合并新的输入数据
            ExecutionContext context = deserializeContext(currentExec);
            if (inputData != null) {
                context.getVariables().putAll(inputData);
            }
            // 加载工作流定义
            CompanyWorkflow definition = loadCompanyWorkflow(currentExec.getWorkflowId());

            // 创建节点实例
            IWorkflowNode node = createNode(definition, nodeKey);
            //执行之前标记上一个节点执行日志为超时
            CompanyAiWorkflowExecLog companyAiWorkflowExecLog = new CompanyAiWorkflowExecLog();
            companyAiWorkflowExecLog.setWorkflowInstanceId(context.getWorkflowInstanceId());
            companyAiWorkflowExecLog.setNodeKey(lastNodeKey);
            companyAiWorkflowExecLog.setStatus(ExecutionStatusEnum.WAITING.getValue());
            List<CompanyAiWorkflowExecLog> companyAiWorkflowExecLogs = companyAiWorkflowExecLogMapper.selectCompanyAiWorkflowExecLogList(companyAiWorkflowExecLog);
            if (null != companyAiWorkflowExecLogs && !companyAiWorkflowExecLogs.isEmpty()) {
                CompanyAiWorkflowExecLog fExecLog = companyAiWorkflowExecLogs.get(0);
                fExecLog.setStatus(ExecutionStatusEnum.TIMEOUT.getValue());
                fExecLog.setEndTime(new Date());
                long durationInMillis = fExecLog.getEndTime().getTime() - fExecLog.getStartTime().getTime();
                fExecLog.setDuration(durationInMillis);
                companyAiWorkflowExecLogMapper.updateById(fExecLog);
            }
            if (node == null) {
                throw new CustomException("节点不存在: " + nodeKey);
            }

            node.execute(context);

        } catch (Exception e) {

        }
    }

    public void workFlowAddExec(){

    }

}
