// Package orchestrator 实现"编排器/规划器"：一个 per-requirement 的 run 聚合根，
// 驱动 6 阶段状态机（planning → prototyping → auditing → implementing → reviewing
// → done）。每个 step 选取一个 agent-kind + prompt，以特权但真实的 owner 身份经
// acp.SessionService 创建一个 ACP session，发一条 prompt 并阻塞等待回合完成
// （session/prompt stopReason），评估阶段网关后推进或回环。run 状态落库到
// orchestrator_runs / orchestrator_steps，每个 step 由 jobs (orchestrator.step) 驱动，
// 因而能跨重启恢复并复用既有 backoff/dead-letter 机制。
//
// agent-to-agent handoff 发生在编排器层：特权身份创建下一个 session，不放松
// checkNotSystemToken。request_subtask MCP 工具让运行中的 agent 在 depth/fan-out
// 限制内入队一个子 step。崩溃的 session 在同一 worktree 上重试/恢复。
package orchestrator

import (
	"context"
	"time"

	"github.com/google/uuid"

	"github.com/yan1h/agent-coding-workflow/internal/project"
)

// RunStatus 是 orchestrator_runs.status 枚举。
type RunStatus string

const (
	RunPending   RunStatus = "pending"
	RunRunning   RunStatus = "running"
	RunPaused    RunStatus = "paused"
	RunSucceeded RunStatus = "succeeded"
	RunFailed    RunStatus = "failed"
	RunCanceled  RunStatus = "canceled"
)

// IsTerminal 报告 run 是否已到终态（不再驱动）。
func (s RunStatus) IsTerminal() bool {
	return s == RunSucceeded || s == RunFailed || s == RunCanceled
}

// IsActive 报告 run 是否处于可驱动状态（pending/running）。paused 不驱动但非终态。
func (s RunStatus) IsActive() bool { return s == RunPending || s == RunRunning }

// StepStatus 是 orchestrator_steps.status 枚举。
type StepStatus string

const (
	StepPending      StepStatus = "pending"
	StepSpawning     StepStatus = "spawning"
	StepRunning      StepStatus = "running"
	StepAwaitingGate StepStatus = "awaiting_gate"
	StepSucceeded    StepStatus = "succeeded"
	StepFailed       StepStatus = "failed"
	StepDead         StepStatus = "dead"
)

// Run 是一次编排运行聚合根。
type Run struct {
	ID            uuid.UUID
	ProjectID     uuid.UUID
	RequirementID uuid.UUID
	WorkspaceID   uuid.UUID
	OwnerID       uuid.UUID
	Status        RunStatus
	CurrentPhase  project.Phase
	Config        RunConfig
	LastError     *string
	CreatedAt     time.Time
	UpdatedAt     time.Time
	EndedAt       *time.Time
}

// Step 是 run 内一次阶段尝试。parent_step_id 非 nil 表示由 request_subtask fan-out。
type Step struct {
	ID           uuid.UUID
	RunID        uuid.UUID
	Phase        project.Phase
	Attempt      int
	ParentStepID *uuid.UUID
	Depth        int
	Status       StepStatus
	AgentKindID  uuid.UUID
	ACPSessionID *uuid.UUID
	Prompt       string
	StopReason   *string
	GateResult   *GateResult
	LastError    *string
	JobID        *uuid.UUID
	CreatedAt    time.Time
	UpdatedAt    time.Time
	EndedAt      *time.Time
}

// RunConfig 是 run 的 per-phase 配置（落 JSONB）。零值合法：PhaseToAgentKind 退回
// defaults，MaxAttemptsPerPhase/MaxDepth/FanOutLimit<=0 时由 service 用配置默认填充。
type RunConfig struct {
	PhaseAgentKinds     map[project.Phase]uuid.UUID `json:"phase_agent_kinds,omitempty"`
	PromptOverrides     map[project.Phase]string    `json:"prompt_overrides,omitempty"`
	MaxAttemptsPerPhase int                         `json:"max_attempts_per_phase,omitempty"`
	MaxDepth            int                         `json:"max_depth,omitempty"`
	FanOutLimit         int                         `json:"fan_out_limit,omitempty"`
}

// GateResult 是一次阶段网关评估结果。Pass=true 推进；Retry=true 且未通过 → 可重试
// （回环本阶段）；Retry=false 且未通过 → 永久失败（dead-letter）。
type GateResult struct {
	Pass   bool           `json:"pass"`
	Retry  bool           `json:"retry"`
	Reason string         `json:"reason,omitempty"`
	Detail map[string]any `json:"detail,omitempty"`
}

// PhaseGate 是可插拔的阶段网关接口。v1 实现见 gate.go。
type PhaseGate interface {
	Evaluate(ctx context.Context, run *Run, step *Step, stopReason string) (GateResult, error)
}

// Caller 表示发起编排操作的用户上下文（与其他模块的 Caller 同语义）。
type Caller struct {
	UserID  uuid.UUID
	IsAdmin bool
}

// StartRunInput 是启动一次编排运行的入参。
type StartRunInput struct {
	ProjectSlug       string
	RequirementNumber int
	StartPhase        project.Phase
	Config            RunConfig
}

// SubtaskInput 是 request_subtask 的入参（由 MCP bridge 透传）。
type SubtaskInput struct {
	Phase       project.Phase
	Prompt      string
	AgentKindID *uuid.UUID
}

// RunFilter 控制 ListRuns 的过滤维度。零值不过滤。
type RunFilter struct {
	ProjectID     *uuid.UUID
	RequirementID *uuid.UUID
	Status        RunStatus
	Limit         int
}

// Service 暴露编排器聚合根的应用服务方法。
type Service interface {
	StartRun(ctx context.Context, c Caller, in StartRunInput) (*Run, error)
	GetRun(ctx context.Context, c Caller, id uuid.UUID) (*Run, error)
	ListRuns(ctx context.Context, c Caller, f RunFilter) ([]*Run, error)
	Pause(ctx context.Context, c Caller, id uuid.UUID) error
	Resume(ctx context.Context, c Caller, id uuid.UUID) error
	Cancel(ctx context.Context, c Caller, id uuid.UUID) error
	// RequestSubtask 由 MCP bridge 调用：运行中的 agent 请求编排器为其当前 step 派生子 step。
	RequestSubtask(ctx context.Context, parentACPSessionID uuid.UUID, in SubtaskInput) (*Step, error)
	// EnqueueStepRedrive 由 acp supervisor onExit 注入的回调间接调用：把崩溃 session 的
	// step 重新入队（带 backoff）。
	EnqueueStepRedrive(ctx context.Context, stepID uuid.UUID, reason string)
}
