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

import type { Task, NewTask, TaskCategory } from '../schema.js';

/**
 * Data for creating a new task.
 * Omits system-managed fields (id, createdAt, updatedAt).
 * At least one of phaseId, initiativeId, or parentTaskId should be provided.
 */
export type CreateTaskData = Omit<NewTask, 'id' | 'createdAt' | 'updatedAt'> & { id?: string };

/**
 * Data for updating a task.
 * Partial of creation data - all fields optional.
 */
export type UpdateTaskData = Partial<CreateTaskData>;

/**
 * Task Repository Port
 *
 * Defines operations for the Task aggregate.
 * Only knows about tasks - no knowledge of parent entities.
 */
export interface TaskRepository {
  /**
   * Create a new task.
   * Generates id and sets timestamps automatically.
   * At least one parent context (phaseId, initiativeId, or parentTaskId) should be set.
   */
  create(data: CreateTaskData): Promise<Task>;

  /**
   * Find a task by its ID.
   * Returns null if not found.
   */
  findById(id: string): Promise<Task | null>;

  /**
   * Find all child tasks of a parent task.
   * Returns tasks ordered by order field.
   * Returns empty array if none exist.
   */
  findByParentTaskId(parentTaskId: string): Promise<Task[]>;

  /**
   * Find all tasks directly linked to an initiative.
   * Returns tasks ordered by order field.
   * Returns empty array if none exist.
   */
  findByInitiativeId(initiativeId: string): Promise<Task[]>;

  /**
   * Find all tasks directly linked to a phase.
   * Returns tasks ordered by order field.
   * Returns empty array if none exist.
   */
  findByPhaseId(phaseId: string): Promise<Task[]>;

  /**
   * Update a task.
   * Throws if task not found.
   * Updates updatedAt timestamp automatically.
   */
  update(id: string, data: UpdateTaskData): Promise<Task>;

  /**
   * Delete a task.
   * Throws if task not found.
   */
  delete(id: string): Promise<void>;

  /**
   * Create a dependency between two tasks.
   * The task identified by taskId will depend on dependsOnTaskId.
   * Both tasks must exist.
   */
  createDependency(taskId: string, dependsOnTaskId: string): Promise<void>;

  /**
   * Get all task IDs that a task depends on.
   * Returns empty array if no dependencies.
   */
  getDependencies(taskId: string): Promise<string[]>;
}
