package com.cmvr.test.flow.context;

import com.alibaba.fastjson2.JSONObject;
import com.cmvr.test.enums.NodeTypeEnum;
import com.cmvr.test.enums.TaskStatusEnum;
import com.cmvr.test.enums.TerminalStatusEnum;
import com.cmvr.test.flow.runtime.event.FlowExecutionEvent;
import com.cmvr.test.flow.runtime.event.FlowExecutionEventPublisher;
import com.cmvr.test.service.ITeNodeInstService;
import com.cmvr.test.service.ITeTaskInstService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 任务实例状态协调器：负责同步日志记录、上下文状态、数据库状态
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class TaskInstHolder {

    private final ITeNodeInstService nodeInstService;
    private final TaskContextManager taskContextManager;
    private final ITeTaskInstService taskInstService;
    private final FlowExecutionEventPublisher eventPublisher;

    public void register(TaskContext context) {
        taskContextManager.register(context);
    }

    public void unRegister(String instId) {
        taskContextManager.unregister(instId);
    }

    public TaskContext getContext(String instId) {
        return taskContextManager.get(instId);
    }

    public boolean isTerminalLocked(String terminalId) {
        return taskContextManager.isTerminalLocked(terminalId);
    }

    public void markRunning(String instId, String taskId, String itemId,
                            String nodeId, String nodeType, String operate,
                            String action, String paramsIn, List<Integer> iterations) {
        nodeInstService.logRunning(instId, taskId, itemId, nodeId, nodeType, operate, action, paramsIn, iterations);
    }

    /**
     * 标记节点执行成功（仅记录节点日志，不更新任务状态）
     *
     * @param instId           任务实例ID
     * @param itemId           检测项ID
     * @param nodeId           节点ID
     * @param pendingItemCount 剩余待执行检测项数量
     * @param nodeType         节点类型
     * @param paramsOut        输出参数
     * @param message          日志消息
     * @param iterations       迭代路径
     */
    public void markNodeSuccess(String instId, String itemId, String nodeId, int pendingItemCount, String nodeType,
                                String paramsOut, String message, List<Integer> iterations) {
        // 仅记录节点执行日志
        nodeInstService.logSuccess(instId, itemId, nodeId, paramsOut, message, iterations);
        
        // 如果是最后一个检测项的END节点，标记任务完成
        if (pendingItemCount == 0 && NodeTypeEnum.END.getCode().equalsIgnoreCase(nodeType)) {
            markTaskCompleted(instId, itemId);
        }
    }

    /**
     * 标记任务执行完成（更新任务状态为SUCCESS，发布完成事件）
     *
     * @param instId 任务实例ID
     * @param itemId 检测项ID
     */
    private void markTaskCompleted(String instId, String itemId) {
        // 先获取上下文（在注销前）
        TaskContext ctx = taskContextManager.get(instId);
        String taskId = ctx != null ? ctx.getTaskId() : null;
        String moduleCode = ctx != null ? ctx.getModuleCode() : null;

        // 更新任务状态为SUCCESS
        syncStatus(instId, TaskStatusEnum.SUCCESS);

        // 注销任务上下文（释放终端锁）
        taskContextManager.unregister(instId);

        // 发布任务完成事件
        eventPublisher.publishEvent(FlowExecutionEvent.builder()
                .eventType(FlowExecutionEvent.EventType.TASK_COMPLETED)
                .instId(instId)
                .taskId(taskId)
                .moduleCode(moduleCode)
                .itemId(itemId)
                .status(TaskStatusEnum.SUCCESS)
                .build());

        log.info("任务执行完成: instId={}, taskId={}", instId, taskId);
    }

    /**
     * 兼容旧方法名（已废弃，请使用 markNodeSuccess）
     * @deprecated 使用 markNodeSuccess 替代
     */
    @Deprecated
    public void markSuccess(String instId, String itemId, String nodeId, int pendingItemCount, String nodeType,
                            String paramsOut, String message, List<Integer> iterations) {
        markNodeSuccess(instId, itemId, nodeId, pendingItemCount, nodeType, paramsOut, message, iterations);
    }

    public void markFailed(String instId, String taskId, String itemId,
                           String nodeId, String nodeType, String operate,
                           String action, String params, String message, List<Integer> iterations) {
        nodeInstService.logFailed(instId, taskId, itemId, nodeId, nodeType, operate, action, params, message,iterations);

        syncStatus(instId, TaskStatusEnum.FAILED);
        
        // 先获取上下文（在注销前）
        TaskContext ctx = taskContextManager.get(instId);
        String moduleCode = ctx != null ? ctx.getModuleCode() : null;
        
        // 注销任务上下文
        taskContextManager.unregister(instId);
        
        // 发布任务失败事件
        eventPublisher.publishEvent(FlowExecutionEvent.builder()
                .eventType(FlowExecutionEvent.EventType.TASK_FAILED)
                .instId(instId)
                .taskId(taskId)
                .moduleCode(moduleCode)
                .itemId(itemId)
                .status(TaskStatusEnum.FAILED)
                .errorMessage(message)
                .build());
    }

    public void syncStatus(String instId, TaskStatusEnum status) {
        TaskContext ctx = taskContextManager.get(instId);
        switch (status) {
            case PAUSED:
                ctx.setPaused(true);
                ctx.setStatus(TaskStatusEnum.PAUSED);
                ctx.setTerminalStatus(TerminalStatusEnum.PAUSED);
                break;
            case STOPPED:
                ctx.setStopped(true);
                ctx.setPaused(false);
                ctx.setTerminalLocked(false);
                break;
        }
        ctx.setStatus(status);
        ctx.updateTimestamp();

        taskInstService.updateStatus(instId, status);
        // 发布任务状态变更事件（暂停/终止/恢复）
        switch (status) {
            case PAUSED:
                eventPublisher.publishEvent(FlowExecutionEvent.builder()
                        .eventType(FlowExecutionEvent.EventType.TASK_PAUSED)
                        .instId(instId).taskId(ctx.getTaskId()).itemId(ctx.getItemId())
                        .moduleCode(ctx.getModuleCode())
                        .status(status).build());
                break;
            case STOPPED:
                eventPublisher.publishEvent(FlowExecutionEvent.builder()
                        .eventType(FlowExecutionEvent.EventType.TASK_STOPPED)
                        .instId(instId).taskId(ctx.getTaskId()).itemId(ctx.getItemId())
                        .moduleCode(ctx.getModuleCode())
                        .status(status).build());
                break;
            default:
                break;
        }
    }

    /**
     * 同步状态并标记为恢复操作（发布 TASK_RESUMED 事件）
     */
    public void syncStatusAsResumed(String instId) {
        TaskContext ctx = taskContextManager.get(instId);
        if (ctx == null) return;
        eventPublisher.publishEvent(FlowExecutionEvent.builder()
                .eventType(FlowExecutionEvent.EventType.TASK_RESUMED)
                .instId(instId).taskId(ctx.getTaskId()).itemId(ctx.getItemId())
                .moduleCode(ctx.getModuleCode())
                .status(TaskStatusEnum.RUNNING).build());
    }

    /**
     * 存储当前节点的输出参数
     */
    public void setNodeOutParams(String instId, String nodeId, List<Integer> iterations, JSONObject params) {
        taskContextManager.setNodeOutParams(instId, nodeId, iterations, params);
    }

    /**
     * 根据 nodeId 和 iterations 获取节点的输出参数
     */
    public JSONObject getNodeOutParams(String instId, String nodeId, List<Integer> iterations) {
        return taskContextManager.getNodeOutParams(instId, nodeId, iterations);
    }
}
