# Routine domain types: Routine, RoutineRun, RoutineStep,
# RoutineTrigger and related enums/inputs.
#
# Step Functions migration: as of plan 2026-05-01-004 (Routines Phase A),
# Routine carries an `engine` partition + Step-Functions-specific fields,
# and three new types (RoutineExecution / RoutineStepEvent /
# RoutineAslVersion) back the Step Functions runtime. RoutineRun and
# RoutineStep are deprecated; they remain shipping through Phase D and
# are removed in Phase E (U15).

enum RoutineStatus {
  ACTIVE
  PAUSED
  ARCHIVED
}

enum RoutineRunStatus {
  PENDING
  RUNNING
  COMPLETED
  FAILED
  CANCELLED
}

enum RoutineEngine {
  LEGACY_PYTHON
  STEP_FUNCTIONS
}

enum RoutineExecutionStatus {
  RUNNING
  SUCCEEDED
  FAILED
  CANCELLED
  AWAITING_APPROVAL
  TIMED_OUT
}

# Routine visibility model (schema follow-up bundle).
# Lower-snake values match the literals already baked into
# admin-ops/checkRoutineVisibility — keeping the enum lower-snake
# avoids a translation layer between the SQL CHECK constraint, the
# GraphQL enum, and the MCP tool's runtime check.
enum RoutineVisibility {
  agent_private
  tenant_shared
}

type Routine {
  id: ID!
  tenantId: ID!
  teamId: ID
  team: Team
  agentId: ID
  agent: Agent
  name: String!
  description: String
  type: String!
  status: String!
  schedule: String
  config: AWSJSON
  # Step Functions migration partition: legacy_python | step_functions.
  # legacy_python rows pre-date Phase A; step_functions rows are the new
  # ASL-backed shape.
  engine: String!
  # Step Functions resource ARNs. Null on legacy_python routines.
  stateMachineArn: String
  stateMachineAliasArn: String
  # Agent-authored markdown summary, regenerated on every publish.
  documentationMd: String
  # Pointer to the latest published version_number in routine_asl_versions.
  currentVersion: Int
  # Visibility model (schema follow-up bundle). Splits the conflated
  # agentId — agentId is the primary execution agent, owningAgentId is
  # the agent that authored / has stewardship. routine_invoke MCP tool
  # enforces ownership via these two fields.
  visibility: RoutineVisibility!
  owningAgentId: ID
  lastRunAt: AWSDateTime
  nextRunAt: AWSDateTime
  # Nullable in Phase A while the type-resolver lands in Phase B U7. A
  # non-null list with no resolver null-propagates and breaks the parent
  # routine query for any client that selects it.
  executions: [RoutineExecution!]
  triggers: [RoutineTrigger!]!
  createdAt: AWSDateTime!
  updatedAt: AWSDateTime!
}

type RoutineTrigger {
  id: ID!
  routineId: ID!
  tenantId: ID!
  triggerType: String!
  config: AWSJSON
  enabled: Boolean!
  createdAt: AWSDateTime!
  updatedAt: AWSDateTime!
}

# ---- Step Functions runtime types (Phase A) ----

type RoutineExecution {
  id: ID!
  tenantId: ID!
  routineId: ID!
  routine: Routine
  stateMachineArn: String!
  aliasArn: String
  versionArn: String
  sfnExecutionArn: String!
  triggerId: ID
  trigger: RoutineTrigger
  triggerSource: String!
  inputJson: AWSJSON
  outputJson: AWSJSON
  status: String!
  startedAt: AWSDateTime
  finishedAt: AWSDateTime
  errorCode: String
  errorMessage: String
  totalLlmCostUsdCents: Int
  stepEvents: [RoutineStepEvent!]!
  # Pointer to the routine_asl_versions row that backed this specific
  # execution. Resolved by (state_machine_arn, version_arn) — the same
  # pair PublishStateMachineVersion stamps onto each version. Run-detail
  # consumes `aslVersion.stepManifestJson` so the graph renders even
  # before any step events arrive. Null for executions whose version
  # ARN wasn't recorded (out-of-band SFN starts).
  aslVersion: RoutineAslVersion
  createdAt: AWSDateTime!
}

type RoutineStepEvent {
  id: ID!
  tenantId: ID!
  executionId: ID!
  nodeId: String!
  recipeType: String!
  status: String!
  startedAt: AWSDateTime
  finishedAt: AWSDateTime
  inputJson: AWSJSON
  outputJson: AWSJSON
  errorJson: AWSJSON
  llmCostUsdCents: Int
  retryCount: Int!
  stdoutS3Uri: String
  stderrS3Uri: String
  stdoutPreview: String
  truncated: Boolean!
  createdAt: AWSDateTime!
}

type RoutineAslVersion {
  id: ID!
  tenantId: ID!
  routineId: ID!
  versionNumber: Int!
  stateMachineArn: String!
  versionArn: String!
  aliasWasPointing: String
  aslJson: AWSJSON!
  markdownSummary: String!
  stepManifestJson: AWSJSON!
  validationWarningsJson: AWSJSON
  publishedByActorId: ID
  publishedByActorType: String
  createdAt: AWSDateTime!
}

type RoutineDefinitionStep {
  nodeId: String!
  recipeId: String!
  recipeName: String!
  label: String!
  args: AWSJSON!
  configFields: [RoutineDefinitionConfigField!]!
}

type RoutineDefinitionConfigField {
  key: String!
  label: String!
  value: AWSJSON
  inputType: String!
  control: String
  required: Boolean!
  editable: Boolean!
  options: [String!]
  placeholder: String
  helpText: String
  min: Float
  max: Float
  pattern: String
}

type RoutineDefinition {
  routineId: ID!
  currentVersion: Int
  versionId: ID
  title: String!
  description: String
  kind: String!
  aslJson: AWSJSON
  markdownSummary: String
  stepManifestJson: AWSJSON
  steps: [RoutineDefinitionStep!]!
}

type RoutineDraft {
  title: String!
  description: String
  kind: String!
  steps: [RoutineDefinitionStep!]!
  asl: AWSJSON!
  markdownSummary: String!
  stepManifest: AWSJSON!
}

type RoutineRecipeConfigField {
  key: String!
  label: String!
  value: AWSJSON
  inputType: String!
  control: String
  required: Boolean!
  editable: Boolean!
  options: [String!]
  placeholder: String
  helpText: String
  min: Float
  max: Float
  pattern: String
}

type RoutineRecipe {
  id: String!
  displayName: String!
  description: String!
  category: String!
  hitlCapable: Boolean!
  defaultArgs: AWSJSON!
  configFields: [RoutineRecipeConfigField!]!
}

# ---- Tenant tool inventory (Phase A scaffold; resolver comes in Phase A U4) ----
#
# Aggregates the fragmented inventory the chat builder agent + tool_invoke
# recipe consume: agents, MCP-server tools, builtin tools, skills, and prior
# step_functions routines. Aggregation logic owned by Phase A U4
# (packages/api/src/lib/routines/recipe-catalog.ts +
#  packages/api/src/graphql/resolvers/routines/tenantToolInventory.query.ts).

type TenantToolInventoryAgent {
  id: ID!
  name: String!
  description: String
}

type TenantToolInventoryTool {
  id: ID!
  source: String! # mcp | builtin
  name: String!
  description: String
  argSchemaJson: AWSJSON
}

type TenantToolInventorySkill {
  id: ID!
  slug: String!
  description: String
}

type TenantToolInventoryRoutine {
  id: ID!
  name: String!
  description: String
  visibility: String
}

type TenantToolInventory {
  agents: [TenantToolInventoryAgent!]!
  tools: [TenantToolInventoryTool!]!
  skills: [TenantToolInventorySkill!]!
  routines: [TenantToolInventoryRoutine!]!
}

# --- Inputs ---

# Phase B U7 cutover: CreateRoutineInput now carries the ASL + markdown
# summary + step manifest the chat builder + publish flow emit. The
# legacy type/schedule/config triple was removed because the new resolver
# provisions a real Step Functions state machine via the ASL document
# instead of the legacy in-row config blob. Schedules attach to a routine
# via setRoutineTrigger after creation; routine type is derived from the
# routine's triggers, not stored on the routines row.
input CreateRoutineInput {
  tenantId: ID!
  teamId: ID
  agentId: ID
  # Visibility model (schema follow-up bundle). Defaults to agent_private
  # when owningAgentId is set, tenant_shared otherwise. The MCP
  # create_routine tool stamps owningAgentId = caller agent id; the
  # admin/mobile new-routine page lets users leave both blank to mint
  # a tenant-shared routine.
  visibility: RoutineVisibility
  owningAgentId: ID
  name: String!
  description: String
  # Optional explicit artifacts for chat/agent authoring paths that
  # already generated ASL. If omitted, createRoutine attempts the
  # server-side authoring MVP from the description/intent and rejects
  # unsupported intents before creating AWS resources.
  asl: AWSJSON
  markdownSummary: String
  stepManifest: AWSJSON
}

input PlanRoutineDraftInput {
  tenantId: ID!
  name: String!
  description: String
  steps: [RoutineDefinitionStepConfigInput!]
}

input ImportN8nRoutineInput {
  tenantId: ID!
  workflowUrl: String!
  name: String
  description: String
  n8nCredentialSlug: String
  pdiCredentialSlug: String
}

# Phase B U7: ASL changes go through publishRoutineVersion. updateRoutine
# narrows to non-ASL metadata edits. `type` is the legacy
# routines.type column (heartbeat | scheduled | cron) still consulted
# by job-triggers; the canonical trigger surface is routine_triggers,
# but the column survives through Phase D's UI cutover.
input UpdateRoutineInput {
  name: String
  description: String
  type: String
  status: String
  schedule: String
  teamId: ID
  agentId: ID
}

input RoutineTriggerInput {
  triggerType: String!
  config: AWSJSON
  enabled: Boolean
}

# Phase B U7 will land the resolver. Schema present in Phase A so codegen
# carries the type signature into all consumers ahead of the resolver.
input PublishRoutineVersionInput {
  routineId: ID!
  asl: AWSJSON!
  markdownSummary: String!
  stepManifest: AWSJSON!
}

input RebuildRoutineVersionInput {
  routineId: ID!
}

input RoutineDefinitionStepConfigInput {
  nodeId: String!
  recipeId: String
  label: String
  args: AWSJSON!
}

input RoutineDefinitionGraphNodeInput {
  nodeId: String!
  recipeId: String
  label: String
  args: AWSJSON
  kind: String
}

input RoutineDefinitionGraphEdgeInput {
  source: String!
  target: String!
  kind: String!
  condition: AWSJSON
  label: String
}

input RoutineDefinitionGraphInput {
  nodes: [RoutineDefinitionGraphNodeInput!]!
  edges: [RoutineDefinitionGraphEdgeInput!]!
  startNodeId: String
}

input UpdateRoutineDefinitionInput {
  routineId: ID!
  steps: [RoutineDefinitionStepConfigInput!]!
  graph: RoutineDefinitionGraphInput
}

input DecideRoutineApprovalInput {
  inboxItemId: ID!
  decision: AWSJSON!
}

# --- Query / Mutation extensions ---

extend type Query {
  routines(
    tenantId: ID!
    teamId: ID
    agentId: ID
    status: RoutineStatus
  ): [Routine!]!
  routine(id: ID!): Routine
  # Phase A schema; resolvers ship in Phase B (U7+U9) and Phase A (U4).
  routineExecution(id: ID!): RoutineExecution
  routineExecutions(
    routineId: ID!
    status: RoutineExecutionStatus
    limit: Int
    cursor: String
  ): [RoutineExecution!]!
  routineStepEvents(executionId: ID!): [RoutineStepEvent!]!
  routineAslVersion(id: ID!): RoutineAslVersion
  routineDefinition(routineId: ID!): RoutineDefinition
  routineRecipeCatalog(tenantId: ID!): [RoutineRecipe!]!
  tenantToolInventory(tenantId: ID!): TenantToolInventory!
}

extend type Mutation {
  planRoutineDraft(input: PlanRoutineDraftInput!): RoutineDraft!
  createRoutine(input: CreateRoutineInput!): Routine!
  importN8nRoutine(input: ImportN8nRoutineInput!): Routine!
  updateRoutine(id: ID!, input: UpdateRoutineInput!): Routine!
  deleteRoutine(id: ID!): Boolean!
  # Phase B U7 cutover: returns RoutineExecution! (the row pre-emptively
  # inserted into routine_executions). Optional `input` is forwarded as
  # the SFN execution input. The legacy RoutineRun! return shape was
  # backed by a never-populated routine_runs table.
  triggerRoutineRun(routineId: ID!, input: AWSJSON): RoutineExecution!

  setRoutineTrigger(
    routineId: ID!
    input: RoutineTriggerInput!
  ): RoutineTrigger!
  deleteRoutineTrigger(id: ID!): Boolean!

  # Phase A schema; resolvers ship in Phase B (U7) and Phase B (U8).
  publishRoutineVersion(input: PublishRoutineVersionInput!): RoutineAslVersion!
  rebuildRoutineVersion(input: RebuildRoutineVersionInput!): RoutineAslVersion!
  updateRoutineDefinition(
    input: UpdateRoutineDefinitionInput!
  ): RoutineDefinition!
  decideRoutineApproval(input: DecideRoutineApprovalInput!): InboxItem!
}
