/**
 * Dispatch Module Types
 *
 * Port interfaces for task and phase dispatch management.
 * DispatchManager and PhaseDispatchManager are PORTS. Implementations are ADAPTERS.
 *
 * This follows the same hexagonal architecture pattern as EventBus and AgentManager:
 * - Interface defines the contract (port)
 * - Implementations can be swapped without changing consumers
 * - Enables testing with in-memory/mock implementations
 */

// =============================================================================
// Dispatch Domain Types
// =============================================================================

/**
 * Represents a task queued for dispatch.
 * Tasks are dispatched when all dependencies complete.
 */
export interface QueuedTask {
  /** Unique identifier for the task */
  taskId: string;
  /** Task priority level */
  priority: 'low' | 'medium' | 'high';
  /** When the task was queued */
  queuedAt: Date;
  /** Task IDs that must complete before this task can be dispatched */
  dependsOn: string[];
}

/**
 * Result of a dispatch operation.
 * Success means task was assigned to an agent; failure means dispatch couldn't happen.
 */
export interface DispatchResult {
  /** Whether the task was successfully dispatched */
  success: boolean;
  /** ID of the task that was dispatched */
  taskId: string;
  /** ID of the agent assigned to the task (only present on success) */
  agentId?: string;
  /** Reason why dispatch failed (only present on failure) */
  reason?: string;
}

// =============================================================================
// DispatchManager Port Interface
// =============================================================================

/**
 * DispatchManager Port Interface
 *
 * Manages task dispatch queue with dependency ordering.
 *
 * Covers requirements:
 * - TASK-04: Dependency-ordered dispatch
 * - TASK-05: Work queue for available agents
 */
export interface DispatchManager {
  /**
   * Queue a task for dispatch.
   * Task will be dispatched when all dependencies complete.
   *
   * @param taskId - ID of the task to queue
   */
  queue(taskId: string): Promise<void>;

  /**
   * Get next dispatchable task.
   * Returns task with all dependencies complete, highest priority first.
   * Returns null if no tasks ready.
   *
   * @returns Next dispatchable task or null
   */
  getNextDispatchable(): Promise<QueuedTask | null>;

  /**
   * Dispatch next available task to an agent.
   * Finds available agent, assigns task, spawns agent.
   * Returns dispatch result.
   *
   * @returns Result of the dispatch operation
   */
  dispatchNext(): Promise<DispatchResult>;

  /**
   * Mark a task as complete.
   * Triggers re-evaluation of dependent tasks.
   *
   * @param taskId - ID of the completed task
   * @param agentId - Optional ID of the agent that completed the task
   */
  completeTask(taskId: string, agentId?: string): Promise<void>;

  /**
   * Mark a task as blocked.
   * Task will not be dispatched until unblocked.
   *
   * @param taskId - ID of the task to block
   * @param reason - Reason for blocking
   */
  blockTask(taskId: string, reason: string): Promise<void>;

  /**
   * Retry a blocked task.
   * Resets status to pending, removes from blocked map, and re-queues for dispatch.
   *
   * @param taskId - ID of the blocked task to retry
   */
  retryBlockedTask(taskId: string): Promise<void>;

  /**
   * Get current queue state.
   * Returns all queued tasks with their dispatch readiness.
   *
   * @returns Queue state with queued, ready, and blocked tasks
   */
  getQueueState(): Promise<{
    /** All queued tasks */
    queued: QueuedTask[];
    /** Tasks ready for dispatch (all dependencies complete) */
    ready: QueuedTask[];
    /** Tasks that are blocked */
    blocked: Array<{ taskId: string; reason: string }>;
  }>;
}

// =============================================================================
// Phase Dispatch Domain Types
// =============================================================================

/**
 * Represents a phase queued for dispatch.
 * Phases are dispatched when all dependencies complete.
 */
export interface QueuedPhase {
  /** Unique identifier for the phase */
  phaseId: string;
  /** Initiative this phase belongs to */
  initiativeId: string;
  /** When the phase was queued */
  queuedAt: Date;
  /** Phase IDs that must complete before this phase can be dispatched */
  dependsOn: string[];
}

/**
 * Result of a phase dispatch operation.
 * Success means phase was dispatched; failure means dispatch couldn't happen.
 */
export interface PhaseDispatchResult {
  /** Whether the phase was successfully dispatched */
  success: boolean;
  /** ID of the phase that was dispatched */
  phaseId: string;
  /** Reason why dispatch failed (only present on failure) */
  reason?: string;
}

// =============================================================================
// PhaseDispatchManager Port Interface
// =============================================================================

/**
 * PhaseDispatchManager Port Interface
 *
 * Manages phase dispatch queue with dependency ordering.
 * Enables queuing and dispatching phases based on their dependencies.
 *
 * Follows exact patterns from DispatchManager for tasks.
 */
export interface PhaseDispatchManager {
  /**
   * Queue a phase for dispatch.
   * Phase will be dispatched when all dependencies complete.
   *
   * @param phaseId - ID of the phase to queue
   */
  queuePhase(phaseId: string): Promise<void>;

  /**
   * Get next dispatchable phase.
   * Returns phase with all dependencies complete.
   * Returns null if no phases ready.
   *
   * @returns Next dispatchable phase or null
   */
  getNextDispatchablePhase(): Promise<QueuedPhase | null>;

  /**
   * Dispatch next available phase.
   * Finds next ready phase and dispatches it.
   * Returns dispatch result.
   *
   * @returns Result of the dispatch operation
   */
  dispatchNextPhase(): Promise<PhaseDispatchResult>;

  /**
   * Mark a phase as complete.
   * Triggers re-evaluation of dependent phases.
   *
   * @param phaseId - ID of the completed phase
   */
  completePhase(phaseId: string): Promise<void>;

  /**
   * Mark a phase as blocked.
   * Phase will not be dispatched until unblocked.
   *
   * @param phaseId - ID of the phase to block
   * @param reason - Reason for blocking
   */
  blockPhase(phaseId: string, reason: string): Promise<void>;

  /**
   * Get current phase queue state.
   * Returns all queued phases with their dispatch readiness.
   *
   * @returns Queue state with queued, ready, and blocked phases
   */
  getPhaseQueueState(): Promise<{
    /** All queued phases */
    queued: QueuedPhase[];
    /** Phases ready for dispatch (all dependencies complete) */
    ready: QueuedPhase[];
    /** Phases that are blocked */
    blocked: Array<{ phaseId: string; reason: string }>;
  }>;
}
