package com.gzzm.lobster.run;

import com.gzzm.lobster.common.RunExitReason;
import com.gzzm.lobster.common.RunStatus;
import net.cyan.thunwind.annotation.ColumnDescription;
import net.cyan.thunwind.annotation.Entity;
import net.cyan.thunwind.annotation.Index;

import java.util.Date;

/**
 * Run —— 一次执行循环的观测记录 / Internal observation record of an execution loop.
 *
 * <p><b>架构红线</b>：业务连续性绝对不依赖本表字段。Run 表仅用于观测、排查、
 * 运维。任何"下一步要做什么""处理到第几项"等语义必须沉淀为 Artifact
 * 或 PendingRequest。
 *
 * <p><b>Design invariant</b>: this table coordinates run lifecycle, durable
 * request replay, worker claim, heartbeat, and recovery. Cognitive continuity
 * still comes from the thread transcript, artifacts, and pending requests.
 */
@Entity(table = "AI_RUN", keys = "runId")
@Index(name = "uk_ai_run_client_request", unique = true, columns = {"userId", "threadId", "clientRequestId"})
public class Run {

    @ColumnDescription(type = "varchar(40)")
    private String runId;

    @Index
    @ColumnDescription(type = "varchar(40)", nullable = false)
    private String threadId;

    @Index
    @ColumnDescription(type = "varchar(40)", nullable = false)
    private String userId;

    /** user_input / confirm / schedule / external_event */
    @ColumnDescription(type = "varchar(40)")
    private String triggerType;

    @ColumnDescription(type = "varchar(200)")
    private String triggerRef;

    @Index
    @ColumnDescription(type = "varchar(120)")
    private String clientRequestId;

    @Index
    @ColumnDescription(type = "varchar(40)")
    private String continuationSourceRunId;

    @ColumnDescription(type = "varchar(80)")
    private String modelId;

    @ColumnDescription(type = "clob")
    private String requestPayloadJson;

    private RunStatus status;

    private RunExitReason exitReason;

    @ColumnDescription(type = "number(6)")
    private Integer turns;

    @ColumnDescription(type = "varchar(80)")
    private String errorCode;

    @ColumnDescription(type = "varchar(2000)")
    private String errorMessage;

    @ColumnDescription(type = "varchar(40)")
    private String cancelReason;

    private Date startedAt;
    private Date heartbeatAt;
    private Date endedAt;
    private Date cancelRequestedAt;

    @ColumnDescription(type = "varchar(80)")
    private String workerId;

    private Date claimedAt;

    public Run() {}

    public String getRunId() { return runId; }
    public void setRunId(String runId) { this.runId = runId; }
    public String getThreadId() { return threadId; }
    public void setThreadId(String threadId) { this.threadId = threadId; }
    public String getUserId() { return userId; }
    public void setUserId(String userId) { this.userId = userId; }
    public String getTriggerType() { return triggerType; }
    public void setTriggerType(String triggerType) { this.triggerType = triggerType; }
    public String getTriggerRef() { return triggerRef; }
    public void setTriggerRef(String triggerRef) { this.triggerRef = triggerRef; }
    public String getClientRequestId() { return clientRequestId; }
    public void setClientRequestId(String clientRequestId) { this.clientRequestId = clientRequestId; }
    public String getContinuationSourceRunId() { return continuationSourceRunId; }
    public void setContinuationSourceRunId(String continuationSourceRunId) { this.continuationSourceRunId = continuationSourceRunId; }
    public String getModelId() { return modelId; }
    public void setModelId(String modelId) { this.modelId = modelId; }
    public String getRequestPayloadJson() { return requestPayloadJson; }
    public void setRequestPayloadJson(String requestPayloadJson) { this.requestPayloadJson = requestPayloadJson; }
    public RunStatus getStatus() { return status; }
    public void setStatus(RunStatus status) { this.status = status; }
    public RunExitReason getExitReason() { return exitReason; }
    public void setExitReason(RunExitReason exitReason) { this.exitReason = exitReason; }
    public Integer getTurns() { return turns; }
    public void setTurns(Integer turns) { this.turns = turns; }
    public String getErrorCode() { return errorCode; }
    public void setErrorCode(String errorCode) { this.errorCode = errorCode; }
    public String getErrorMessage() { return errorMessage; }
    public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
    public String getCancelReason() { return cancelReason; }
    public void setCancelReason(String cancelReason) { this.cancelReason = cancelReason; }
    public Date getStartedAt() { return startedAt; }
    public void setStartedAt(Date startedAt) { this.startedAt = startedAt; }
    public Date getHeartbeatAt() { return heartbeatAt; }
    public void setHeartbeatAt(Date heartbeatAt) { this.heartbeatAt = heartbeatAt; }
    public Date getEndedAt() { return endedAt; }
    public void setEndedAt(Date endedAt) { this.endedAt = endedAt; }
    public Date getCancelRequestedAt() { return cancelRequestedAt; }
    public void setCancelRequestedAt(Date cancelRequestedAt) { this.cancelRequestedAt = cancelRequestedAt; }
    public String getWorkerId() { return workerId; }
    public void setWorkerId(String workerId) { this.workerId = workerId; }
    public Date getClaimedAt() { return claimedAt; }
    public void setClaimedAt(Date claimedAt) { this.claimedAt = claimedAt; }
}
