/**
 * Dependency injection interfaces for the Ion workflow engine.
 *
 * These interfaces define the contracts that the engine requires from its
 * runtime environment. Concrete implementations are provided by the
 * platform layer (CLI, server, etc.).
 */

export interface IWorkflowPlatform {
  /** Send a text message to the conversation channel. */
  sendMessage(
    conversationId: string,
    message: string,
    metadata?: Record<string, unknown>,
  ): Promise<void>;

  /** Whether the platform supports streaming responses. */
  getStreamingMode(): boolean;

  /** Optional structured event emission (e.g. approval requests). */
  sendStructuredEvent?(
    conversationId: string,
    event: Record<string, unknown>,
  ): Promise<void>;
}

/** Configuration for a single AI provider. */
export interface ProviderConfig {
  /** Provider identifier (e.g. "openai", "anthropic"). */
  provider: string;
  /** Model name (e.g. "gpt-4o", "claude-sonnet-4-20250514"). */
  model?: string;
  /** Additional provider-specific options. */
  options?: Record<string, unknown>;
}

/** Folder-level command configuration. */
export interface CommandFolderConfig {
  /** Path to the commands folder. */
  path: string;
  /** Whether commands are enabled by default. */
  enabled?: boolean;
}

export interface WorkflowConfig {
  /** Default assistant identifier. */
  assistant: string;
  /** Named provider configurations keyed by provider id. */
  assistants: Record<string, ProviderConfig>;
  /** Environment variables available to the workflow. */
  envVars: Record<string, string>;
  /** Command folder configuration. */
  commands: CommandFolderConfig;
  /** Base git branch for the workflow (optional). */
  baseBranch?: string;
  /** Path to documentation directory (optional). */
  docsPath?: string;
}

/** Minimal data required to create a workflow run. */
export interface CreateWorkflowRunData {
  workflowPath: string;
  workflowName: string;
  trigger: string;
  input: Record<string, unknown>;
}

/** Status of a workflow run. */
export type WorkflowRunStatus =
  | 'pending'
  | 'running'
  | 'completed'
  | 'failed'
  | 'cancelled';

/** A persisted workflow run record. */
export interface WorkflowRun {
  id: string;
  workflowPath: string;
  workflowName: string;
  status: WorkflowRunStatus;
  trigger: string;
  input: Record<string, unknown>;
  output?: Record<string, unknown>;
  error?: string;
  createdAt: Date;
  updatedAt: Date;
}

/** A single event within a workflow run (node start/complete/etc.). */
export interface WorkflowEvent {
  id: string;
  runId: string;
  nodeId?: string;
  type: string;
  data: Record<string, unknown>;
  createdAt: Date;
}

export interface IWorkflowStore {
  // -- Run lifecycle -------------------------------------------------------

  /** Create a new workflow run. */
  createWorkflowRun(data: CreateWorkflowRunData): Promise<WorkflowRun>;

  /** Retrieve a workflow run by id. */
  getWorkflowRun(id: string): Promise<WorkflowRun | null>;

  /** Update a workflow run. */
  updateWorkflowRun(
    id: string,
    data: Partial<WorkflowRun>,
  ): Promise<WorkflowRun>;

  /** Mark a workflow run as failed. */
  failWorkflowRun(id: string, error: string): Promise<WorkflowRun>;

  /** Get the current status of a workflow run. */
  getWorkflowRunStatus(id: string): Promise<WorkflowRunStatus | null>;

  // -- Events --------------------------------------------------------------

  /** Record a workflow event. */
  createWorkflowEvent(event: Omit<WorkflowEvent, 'id' | 'createdAt'>): Promise<WorkflowEvent>;

  /** Get completed DAG node outputs for a run. */
  getCompletedDagNodeOutputs(
    runId: string,
  ): Promise<Record<string, Record<string, unknown>>>;

  // -- Active runs ---------------------------------------------------------

  /** Find an active (non-terminal) run for a given workflow path. */
  getActiveWorkflowRunByPath(
    path: string,
    opts?: { excludeId?: string },
  ): Promise<WorkflowRun | null>;

  // -- Codebase ------------------------------------------------------------

  /** Get a codebase record by id. */
  getCodebase(id: string): Promise<Record<string, unknown> | null>;

  /** Get environment variables for a codebase. */
  getCodebaseEnvVars(id: string): Promise<Record<string, string>>;

  // -- Resumption ----------------------------------------------------------

  /** Resume a paused workflow run. */
  resumeWorkflowRun(id: string): Promise<WorkflowRun>;
}

export interface IAgentProvider {
  /** Provider identifier. */
  readonly providerId: string;

  /** Send a prompt and return the response. */
  sendPrompt(prompt: string, options?: Record<string, unknown>): Promise<string>;
}

export interface WorkflowDeps {
  /** Persistence store. */
  store: IWorkflowStore;

  /** Load workflow config from a working directory. */
  loadConfig(cwd: string): Promise<WorkflowConfig>;

  /** Get an agent provider by its provider id. */
  getAgentProvider(providerId: string): IAgentProvider;

  /** Resolve a bot-level GitHub token (optional). */
  resolveBotGitHubToken?(): Promise<string | undefined>;

  /** Get the user-level GitHub token (optional). */
  getUserGithubToken?(): Promise<string | undefined>;

  /** Whether per-user GitHub token resolution is enabled (optional). */
  isPerUserGitHubEnabled?(): boolean;
}