/**
 * AirCoding Task Contracts
 *
 * Implements TaskType, TaskScope, TaskDependencySpec, VerificationPolicy,
 * TaskConstraints, TaskContextRefs, WorkerOutputContract, TaskSpec, TaskGraph,
 * Scheduler interfaces, and storage.ts symbols (TransactionManager, Repository)
 * per interface-contracts-v1.md §9 and system-detailed-design.md §3.
 */

// Import IDs needed for these types
import type {
  SessionID,
  TaskID,
  AgentID,
  ArtifactID,
  ProviderID,
  ModelID,
  WorkspaceID,
  WaveID,
  UUID,
  ISOTimeString,
} from './ids.js'

// Re-export ModelAssignment from provider.ts (canonical definition per DD §3)
// and make it available to this module for scheduler types
import type { ModelAssignment } from './provider.js'
export type { ModelAssignment } from './provider.js'

// =============================================================================
// §9 — Task and Scheduler Contracts
// =============================================================================

/**
 * Task types supported by the scheduler and worker system.
 * Maps to specific worker roles per DD §8.3.
 */
export type TaskType = 'execute' | 'review' | 'debug' | 'compact' | 'mine_experience' | 'docs'

/**
 * Task status lifecycle states.
 */
export type TaskStatus = 'pending' | 'running' | 'completed' | 'failed' | 'blocked' | 'cancelled' | 'interrupted'

/**
 * Task dependency types defining relationship semantics.
 */
export type TaskDependencyType = 'hard' | 'soft' | 'conflict' | 'serialization'

/**
 * Specification for a task dependency.
 */
export interface TaskDependencySpec {
  depends_on_task_id: TaskID
  dependency_type: TaskDependencyType
  reason?: string
  source?: 'architecture' | 'scheduler' | 'worker' | 'user' | 'system'
}

/**
 * Defines the scope boundaries for a task's execution.
 */
export interface TaskScope {
  write_area?: string
  expected_files?: string[]
  allowed_paths?: string[]
  denied_paths?: string[]
}

/**
 * Verification policy for task completion.
 */
export interface VerificationPolicy {
  commands?: string[]
  required: boolean
  fallback_allowed: boolean
}

/**
 * Execution constraints for a task.
 */
export interface TaskConstraints {
  max_turns: number
  soft_timeout_ms: number
  hard_timeout_ms: number
  retry_budget: number
  model_policy: 'scheduler_forced' | 'agent_select'
  model_provider_id?: ProviderID
  model_id?: ModelID
}

/**
 * References to contextual artifacts and other tasks.
 */
export interface TaskContextRefs {
  plan_ref?: string
  arc_ref?: string
  parent_task_results?: ArtifactID[]
  artifacts?: ArtifactID[]
}

/**
 * Worker output contract types - the result structure each worker type produces.
 */
export type WorkerOutputContract =
  | 'ExecutorResult'
  | 'ReviewerResult'
  | 'DebuggerResult'
  | 'CompactorResult'
  | 'ExperienceMinerResult'

/**
 * Complete task specification for scheduler and workers.
 * Matches DD §22.1 specification.
 */
export interface TaskSpec {
  id: TaskID
  type: TaskType
  title: string
  description: string
  acceptance_criteria: string[]
  scope: TaskScope
  dependencies: TaskDependencySpec[]
  verification: VerificationPolicy
  constraints: TaskConstraints
  context_refs: TaskContextRefs
  output_contract: WorkerOutputContract
}

/**
 * A task node within the task graph with runtime state.
 */
export interface TaskNode {
  task_id: TaskID
  spec: TaskSpec
  status: TaskStatus
  assigned_agent_id?: AgentID
  retry_count: number
  workspace_id?: WorkspaceID
}

/**
 * Task graph representing all tasks and dependencies for a session.
 */
export interface TaskGraph {
  session_id: SessionID
  tasks: Map<TaskID, TaskNode>
  dependencies: Array<{
    id: UUID
    task_id: TaskID
    depends_on_task_id: TaskID
    dependency_type: TaskDependencyType
    reason?: string
    created_at: ISOTimeString
  }>
}

/**
 * Workspace creation strategy for task execution.
 */
export interface WorkspacePlan {
  strategy: 'main' | 'worktree' | 'isolated_copy'
  path?: string
  base_ref?: string
  branch_name?: string
  reason: string
}

/**
 * Scheduler wave plan - the planned execution wave for one cycle.
 */
export interface SchedulerWavePlan {
  wave_id: WaveID
  runnable_task_ids: TaskID[]
  serialized_task_ids: TaskID[]
  workspace_assignments: Record<TaskID, WorkspacePlan>
  model_assignments: Record<TaskID, ModelAssignment>
  reason: string
}

/**
 * Result of a scheduler run.
 */
export interface SchedulerRunResult {
  status: 'completed' | 'blocked' | 'cancelled' | 'idle'
  completed_task_ids: TaskID[]
  blocked_task_ids: TaskID[]
  summary: string
}

/**
 * Scheduler interface - the orchestration service for task execution.
 * Per DD §7.1, the Scheduler is an orchestration service, not a coding agent.
 */
export interface Scheduler {
  create_tasks(session_id: SessionID, specs: TaskSpec[]): Promise<void>
  add_dependency(session_id: SessionID, task_id: TaskID, dependency: TaskDependencySpec): Promise<void>
  load_graph(session_id: SessionID): Promise<TaskGraph>
  run_until_idle(session_id: SessionID): Promise<SchedulerRunResult>
  cancel_task(task_id: TaskID, reason: string): Promise<void>
}

// =============================================================================
// §6 — Transaction and Storage Contracts (merged from storage.ts per DD §3)
// =============================================================================

/**
 * Handle for an active database transaction.
 * The optional `db` property carries the transaction-scoped database handle
 * so that repository methods can execute within the same transaction.
 */
export interface TransactionHandle {
  id: string
  db?: any  // DatabaseHandle from runtime — typed as any to avoid cross-package import
}

/**
 * Handle for an open database connection.
 */
export interface DatabaseHandle {
  path: string
}

/**
 * Transaction manager interface for database operations.
 */
export interface TransactionManager {
  transaction<T>(fn: (tx: TransactionHandle) => Promise<T>): Promise<T>
}

/**
 * Generic repository interface for CRUD operations.
 * @template TRecord - The record type for the repository
 * @template TInsert - The insert type (typically record without auto-generated fields)
 * @template TUpdate - The update patch type
 */
export interface Repository<TRecord, TInsert, TUpdate> {
  get(id: string, tx?: TransactionHandle): Promise<TRecord | undefined>
  insert(record: TInsert, tx?: TransactionHandle): Promise<void>
  update(id: string, patch: TUpdate, tx?: TransactionHandle): Promise<void>
}

/**
 * Task record as stored in the database.
 * Mirrors db-schema §7 columns.
 */
export interface TaskRecord {
  id: TaskID
  session_id: SessionID
  type: TaskType
  status: TaskStatus
  title: string
  task_spec_json: string
  worker_result_json?: string
  assigned_agent_id?: AgentID
  workspace_id?: WorkspaceID
  retry_count: number
  created_at: ISOTimeString
  started_at?: ISOTimeString
  completed_at?: ISOTimeString
  heartbeat_at?: ISOTimeString
  metadata_json?: string
}

/**
 * Task insert type - fields required when creating a new task.
 * Omits computed/auto fields.
 */
export type TaskInsert = Omit<
  TaskRecord,
  'retry_count' | 'started_at' | 'completed_at' | 'heartbeat_at' | 'worker_result_json'
> & {
  retry_count?: number
}

/**
 * Task update patch type.
 */
export type TaskUpdate = Partial<Omit<TaskRecord, 'id' | 'session_id' | 'created_at'>>

/**
 * Extended repository interface for task-specific operations.
 */
export interface TaskRepository extends Repository<TaskRecord, TaskInsert, TaskUpdate> {
  /**
   * List tasks by status filter.
   */
  list_by_status(session_id: SessionID, statuses: TaskStatus[], tx?: TransactionHandle): Promise<TaskRecord[]>
  /**
   * List runnable task candidates - tasks that have all dependencies satisfied.
   */
  list_runnable_candidates(session_id: SessionID, tx?: TransactionHandle): Promise<TaskRecord[]>
}

/**
 * Task dependency record as stored in the database.
 */
export interface TaskDependencyRecord {
  id: UUID
  session_id: SessionID
  task_id: TaskID
  depends_on_task_id: TaskID
  dependency_type: TaskDependencyType
  reason?: string
  created_at: ISOTimeString
}