/**
 * Agent Repository Port Interface
 *
 * Port for Agent aggregate operations.
 * Implementations (Drizzle, etc.) are adapters.
 */

import type { Agent } from '../schema.js';
import type { AgentMode } from '../../agent/types.js';

/**
 * Agent status values.
 */
export type AgentStatus = 'idle' | 'running' | 'waiting_for_input' | 'stopped' | 'crashed';

/**
 * Data for creating a new agent.
 * Omits system-managed fields and makes optional fields explicit.
 */
export interface CreateAgentData {
  name: string;
  worktreeId: string;
  taskId?: string | null;
  initiativeId?: string | null;
  sessionId?: string | null;
  status?: AgentStatus;
  mode?: AgentMode; // Defaults to 'execute' if not provided
  provider?: string; // Defaults to 'claude' if not provided
  accountId?: string | null;
}

/**
 * Data for updating an existing agent.
 * All fields optional. System-managed fields (id, createdAt, updatedAt) are excluded.
 */
export interface UpdateAgentData {
  name?: string;
  worktreeId?: string;
  taskId?: string | null;
  initiativeId?: string | null;
  sessionId?: string | null;
  status?: AgentStatus;
  mode?: AgentMode;
  provider?: string;
  accountId?: string | null;
  pid?: number | null;
  exitCode?: number | null;
  outputFilePath?: string | null;
  result?: string | null;
  pendingQuestions?: string | null;
  userDismissedAt?: Date | null;
  updatedAt?: Date;
}

/**
 * Agent Repository Port
 *
 * Defines operations for the Agent aggregate.
 * Enables agent state persistence for session resumption and listing.
 */
export interface AgentRepository {
  /**
   * Create a new agent.
   * Generates id and sets timestamps automatically.
   * Name must be unique.
   */
  create(agent: CreateAgentData): Promise<Agent>;

  /**
   * Find an agent by its ID.
   * Returns null if not found.
   */
  findById(id: string): Promise<Agent | null>;

  /**
   * Find an agent by its human-readable name.
   * Returns null if not found.
   */
  findByName(name: string): Promise<Agent | null>;

  /**
   * Find an agent by its associated task.
   * Returns null if no agent is assigned to that task.
   */
  findByTaskId(taskId: string): Promise<Agent | null>;

  /**
   * Find an agent by its Claude CLI session ID.
   * Used for session resumption.
   * Returns null if not found.
   */
  findBySessionId(sessionId: string): Promise<Agent | null>;

  /**
   * Find all agents.
   * Returns empty array if none exist.
   */
  findAll(): Promise<Agent[]>;

  /**
   * Find agents by status.
   * Returns empty array if no agents have that status.
   */
  findByStatus(status: AgentStatus): Promise<Agent[]>;

  /**
   * Update an agent with partial data.
   * Only provided fields are updated, others remain unchanged.
   * Throws if agent not found.
   * Updates updatedAt timestamp automatically.
   */
  update(id: string, data: UpdateAgentData): Promise<Agent>;

  /**
   * Delete an agent.
   * Throws if agent not found.
   */
  delete(id: string): Promise<void>;
}
