/**
 * Gantt chart types
 * Extends base Task type with start/end dates for timeline visualization
 */

import type { Task } from "@mosaic/shared";

/**
 * Extended task type for Gantt chart display
 * Adds explicit start and end dates required for timeline visualization
 */
export interface GanttTask extends Task {
  /** Start date for the task (required for Gantt visualization) */
  startDate: Date;
  /** End date for the task (maps to dueDate but explicit for clarity) */
  endDate: Date;
  /** Optional array of task IDs that this task depends on */
  dependencies?: string[];
  /** Whether this task is a milestone (zero-duration marker) */
  isMilestone?: boolean;
}

/**
 * Position and dimensions for a Gantt bar in the timeline
 */
export interface GanttBarPosition {
  /** Left offset from timeline start (in pixels or percentage) */
  left: string;
  /** Width of the bar (in pixels or percentage) */
  width: string;
  /** Top offset for vertical positioning */
  top: number;
}

/**
 * Date range for the entire Gantt chart timeline
 */
export interface TimelineRange {
  /** Earliest date to display */
  start: Date;
  /** Latest date to display */
  end: Date;
  /** Total number of days in the range */
  totalDays: number;
}

/**
 * Props for the main GanttChart component
 */
export interface GanttChartProps {
  /** Tasks to display in the Gantt chart */
  tasks: GanttTask[];
  /** Optional callback when a task bar is clicked */
  onTaskClick?: (task: GanttTask) => void;
  /** Optional height for the chart container */
  height?: number;
  /** Whether to show task dependencies (default: false) */
  showDependencies?: boolean;
}

/**
 * Type guard to check if a value is a valid date string
 */
function isDateString(value: unknown): value is string {
  return typeof value === "string" && !isNaN(Date.parse(value));
}

/**
 * Type guard to check if a value is an array of strings
 */
function isStringArray(value: unknown): value is string[] {
  return Array.isArray(value) && value.every((item) => typeof item === "string");
}

/**
 * Helper to convert a base Task to GanttTask
 * Uses createdAt as startDate if not in metadata, dueDate as endDate
 */
export function toGanttTask(task: Task): GanttTask | null {
  // For Gantt chart, we need both start and end dates
  const metadataStartDate = task.metadata.startDate;
  const startDate = isDateString(metadataStartDate) ? new Date(metadataStartDate) : task.createdAt;

  const endDate = task.dueDate ?? new Date();

  // Extract dependencies with type guard
  const metadataDependencies = task.metadata.dependencies;
  const dependencies = isStringArray(metadataDependencies) ? metadataDependencies : undefined;

  const ganttTask: GanttTask = {
    ...task,
    startDate,
    endDate,
    isMilestone: task.metadata.isMilestone === true,
  };

  if (dependencies) {
    ganttTask.dependencies = dependencies;
  }

  return ganttTask;
}

/**
 * Helper to get all GanttTasks from an array of Tasks
 * Filters out tasks that don't have valid date ranges
 */
export function toGanttTasks(tasks: Task[]): GanttTask[] {
  return tasks.map(toGanttTask).filter((task): task is GanttTask => task !== null);
}
