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);
    }

    public void markSuccess(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);
        syncStatus(instId, TaskStatusEnum.SUCCESS);
        // 如果没有下一个检测项要执行 且是end节点 注销任务上下文
        if (pendingItemCount == 0 && nodeType.equalsIgnoreCase(NodeTypeEnum.END.getCode())) {
            TaskContext ctx = taskContextManager.get(instId);
            taskContextManager.unregister(instId);
            // 发布任务完成事件
            eventPublisher.publishEvent(FlowExecutionEvent.builder()
                    .eventType(FlowExecutionEvent.EventType.TASK_COMPLETED)
                    .instId(instId)
                    .taskId(ctx != null ? ctx.getTaskId() : null)
                    .itemId(itemId)
                    .status(TaskStatusEnum.SUCCESS)
                    .build());
        }
    }

    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);
        taskContextManager.unregister(instId);
        // 发布任务失败事件
        eventPublisher.publishEvent(FlowExecutionEvent.builder()
                .eventType(FlowExecutionEvent.EventType.TASK_FAILED)
                .instId(instId)
                .taskId(taskId)
                .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())
                        .status(status).build());
                break;
            case STOPPED:
                eventPublisher.publishEvent(FlowExecutionEvent.builder()
                        .eventType(FlowExecutionEvent.EventType.TASK_STOPPED)
                        .instId(instId).taskId(ctx.getTaskId()).itemId(ctx.getItemId())
                        .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())
                .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);
    }
}
