import {
  type DownloadEvent,
  type DownloadMeta,
  type DownloadOptions,
  type CollectionContext,
  type MediaKind
} from '@shared/ipc'

// Single-sourced from the IPC contract (L105) and re-exported so existing
// `import { MediaKind } from '../store/downloads'` sites keep working.
export type { MediaKind }

export type DownloadStatus =
  'queued' | 'downloading' | 'paused' | 'saved' | 'completed' | 'error' | 'canceled'

/** An exact probed format chosen for a download (omitted for the preset path). */
export interface ChosenFormat {
  id: string
  hasAudio: boolean
  label: string
}

export interface DownloadItem {
  id: string
  url: string
  title: string
  channel?: string
  durationLabel?: string
  thumbnail?: string
  kind: MediaKind
  quality: string
  status: DownloadStatus
  /** 0..1 */
  progress: number
  /** raw transfer rate in bytes/sec (formatted for display via @shared/format) */
  speedBytesPerSec?: number
  /** raw time remaining in seconds (formatted for display via @shared/format) */
  etaSeconds?: number
  sizeLabel?: string
  /** yt-dlp reported no total size -- render the bar indeterminate, not 0% (L137) */
  sizeUnknown?: boolean
  /** true once the main download stream finished and yt-dlp is fetching the
   *  remaining stream / merging / post-processing -- the bar goes indeterminate
   *  instead of visibly restarting 0→100% for the second stream (SR7) */
  finishing?: boolean
  filePath?: string
  error?: string
  /** exact format carried so retry re-downloads the same thing */
  formatId?: string
  formatHasAudio?: boolean
  /** per-download post-processing override (omitted = use persisted defaults) */
  options?: DownloadOptions
  /** per-download custom-command override (omitted = use the persisted default template) */
  extraArgs?: string
  /** raw trim spec -- time ranges to keep (parsed to --download-sections in main) */
  trim?: string
  /** epoch ms to auto-start a 'saved' item; undefined = parked indefinitely (Phase M) */
  scheduledFor?: number
  /** private download -- completion is never recorded to history */
  incognito?: boolean
  /** metadata already fetched at probe time; forwarded to main so it skips a redundant probe */
  probedMeta?: DownloadMeta
  /** media-manager folder context -- files this into <channel>/<playlist>/<NNN> - <title> */
  collection?: CollectionContext
  /** per-download collection folder-layout override (a MediaProfile's outputTemplate) */
  collectionOutputTemplate?: string
  /** when set, the source MediaItem id this download came from -- marked downloaded on completion */
  mediaItemId?: string
}

/** Options accepted when enqueuing a URL (shared by addFromUrl + addMany). */
export interface AddOptions {
  format?: ChosenFormat
  title?: string
  channel?: string
  durationLabel?: string
  thumbnail?: string
  options?: DownloadOptions
  extraArgs?: string
  trim?: string
  /** when set and in the future, the item starts 'saved' and auto-queues at this time */
  scheduledFor?: number
  incognito?: boolean
  collection?: CollectionContext
  collectionOutputTemplate?: string
  mediaItemId?: string
}

/** One URL to enqueue in a single addMany batch. */
export interface AddEntry {
  url: string
  kind: MediaKind
  quality: string
  opts?: AddOptions
}

export interface DownloadState {
  items: DownloadItem[]
  addFromUrl: (url: string, kind: MediaKind, quality: string, opts?: AddOptions) => void
  /**
   * Enqueue many URLs at once with a single state update and a single pump, so
   * queuing an entire channel (1000s of items) doesn't churn the store O(n²) the
   * way looping addFromUrl would.
   */
  addMany: (entries: AddEntry[]) => void
  retry: (id: string) => void
  /** re-queue every failed item at once (Phase M) */
  retryAll: () => void
  /** stop a running download but keep its partial file for a later resume (Phase M) */
  pause: (id: string) => void
  /** re-queue a paused download; yt-dlp continues its partial file on relaunch */
  resume: (id: string) => void
  /** move a queued item to the front of the promotion order ("download next", Phase M) */
  prioritize: (id: string) => void
  /** park a queued item indefinitely as 'saved' (Phase M) */
  saveForLater: (id: string) => void
  /** un-park a 'saved' item back into the queue now (clears any schedule) */
  queueNow: (id: string) => void
  /** internal: promote any 'saved' item whose scheduledFor time has arrived */
  promoteDueScheduled: () => void
  cancel: (id: string) => void
  /** cancel every active (downloading + queued) item at once (UX15) */
  cancelAll: () => void
  remove: (id: string) => void
  clearFinished: () => void
  openFile: (id: string) => void
  showInFolder: (id: string) => void
  /** promote queued items into free download slots (respects MAX_CONCURRENT) */
  pump: () => void
  /** internal: apply a main-process download event */
  applyEvent: (ev: DownloadEvent) => void
  /** Load the persisted queue from main on launch (M4); no-op in preview. */
  hydrate: () => void
}
