///|
pub(all) enum ModelStage {
  Stage1
  Stage2
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) enum RoutineEventKind {
  PhaseStarted
  PhaseCompleted
  ToolPlanned
  ModelOutputCaptured
  ValidationCaptured
  RecordPersisted
  RoutineCancelled
  RoutineFailed
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct RoutineRequest {
  run_id : @domain.RunId
  operator_request : String
  snapshot : @domain.KlineSnapshot
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct ModelUsage {
  prompt_tokens : Int
  completion_tokens : Int
  total_tokens : Int
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct StageOutput {
  stage : ModelStage
  content : String
  reasoning_content : String?
  usage : ModelUsage?
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct RoutineEvent {
  run_id : @domain.RunId
  index : Int
  phase : RoutinePhase
  kind : RoutineEventKind
  message : String
  at_ms : Int64
} derive(Debug, Eq, ToJson, FromJson)

///|
pub(all) struct RoutineResponse {
  request : RoutineRequest
  plan : RoutinePlan
  events : Array[RoutineEvent]
  record : @domain.AnalysisRecord
} derive(Debug, Eq, ToJson, FromJson)

///|
pub fn routine_request(
  run_id : @domain.RunId,
  operator_request : String,
  snapshot : @domain.KlineSnapshot,
) -> RoutineRequest {
  { run_id, operator_request, snapshot }
}

///|
pub fn model_usage(prompt_tokens : Int, completion_tokens : Int) -> ModelUsage {
  {
    prompt_tokens,
    completion_tokens,
    total_tokens: prompt_tokens + completion_tokens,
  }
}

///|
pub fn stage_output(
  stage : ModelStage,
  content : String,
  reasoning_content : String?,
  usage : ModelUsage?,
) -> StageOutput {
  { stage, content, reasoning_content, usage }
}

///|
pub fn routine_event(
  run_id : @domain.RunId,
  index : Int,
  phase : RoutinePhase,
  kind : RoutineEventKind,
  message : String,
  at_ms? : Int64 = 0L,
) -> RoutineEvent {
  { run_id, index, phase, kind, message, at_ms }
}

///|
pub fn phase_events(
  run_id : @domain.RunId,
  phases : Array[RoutinePhase],
  start_index? : Int = 0,
) -> Array[RoutineEvent] {
  let events : Array[RoutineEvent] = []
  let mut index = start_index
  for phase in phases {
    events.push(
      routine_event(
        run_id,
        index,
        phase,
        PhaseStarted,
        "started \{phase.label()}",
      ),
    )
    index += 1
    events.push(
      routine_event(
        run_id,
        index,
        phase,
        PhaseCompleted,
        "completed \{phase.label()}",
      ),
    )
    index += 1
  }
  events
}

///|
pub fn append_event(
  events : Array[RoutineEvent],
  event : RoutineEvent,
) -> Array[RoutineEvent] {
  let next = events.copy()
  next.push(event)
  next
}