// Mirrors of the Rust structs in src-tauri/src/models.rs. Field names match
// serde's output exactly so no mapping layer is needed.

export type DownloadState =
  | "queued"
  | "running"
  | "done"
  | "failed"
  | "cancelled";

export interface ChannelWithCount {
  id: string;
  title: string;
  url: string;
  video_count: number;
  downloaded_count: number;
  /** Why this channel's last refresh failed, if it did. */
  last_error: string | null;
}

export interface FeedItem {
  id: string;
  channel_id: string;
  channel_title: string;
  title: string;
  description: string;
  /** Unix seconds. */
  published: number;
  thumb_url: string;
  thumb_path: string | null;
  views: number;
  is_short: boolean;
  state: DownloadState | null;
  path: string | null;
  pct: number | null;
  error: string | null;
  /** Seconds watched, and the video's length — drives the feed progress bar. */
  position: number | null;
  duration: number | null;
}

export interface FeedFilter {
  channel_id?: string | null;
  search?: string | null;
  downloaded_only: boolean;
  hide_shorts: boolean;
  limit?: number | null;
}

export interface Prereqs {
  yt_dlp: string | null;
  ffmpeg: string | null;
  library_path: string;
}

export interface RefreshSummary {
  channels: number;
  new_videos: number;
  failures: string[];
}

export interface RefreshProgress {
  done: number;
  total: number;
  channel: string;
}

export interface DownloadProgressEvent {
  video_id: string;
  pct: number | null;
  bytes_done: number;
  bytes_total: number | null;
  speed: number | null;
  eta: number | null;
}

export interface DownloadStateEvent {
  video_id: string;
  state: DownloadState;
  error: string | null;
  path: string | null;
}

export interface ImportPreview {
  incoming: number;
  removed_channels: number;
  removed_videos: number;
  removed_downloads: number;
}

/** "best" or a maximum height in pixels. */
export type Quality = "best" | "2160" | "1440" | "1080" | "720" | "480";

export interface Stream {
  url: string | null;
  playlist: string | null;
}

export const QUALITIES: Array<{ value: Quality; label: string }> = [
  { value: "best", label: "Best available (up to 4K)" },
  { value: "2160", label: "2160p — 4K" },
  { value: "1440", label: "1440p — 2K" },
  { value: "1080", label: "1080p" },
  { value: "720", label: "720p" },
  { value: "480", label: "480p" },
];

/** Streaming tops out at 1080p — YouTube's HLS carries nothing higher. */
export const STREAM_QUALITIES: Array<{ value: Quality; label: string }> = [
  { value: "best", label: "Best available (adaptive)" },
  { value: "1080", label: "1080p" },
  { value: "720", label: "720p" },
  { value: "480", label: "480p" },
];

/** How subtitles look, set from the player's subtitle menu. */
export interface SubStyle {
  /** Percentage of the player's default cue size. */
  size: number;
  font: "sans" | "serif" | "mono";
  place: "bottom" | "raised" | "top";
}

export const DEFAULT_SUB_STYLE: SubStyle = { size: 85, font: "sans", place: "bottom" };

export const SUB_SIZES: Array<{ value: number; label: string }> = [
  { value: 65, label: "S" },
  { value: 85, label: "M" },
  { value: 110, label: "L" },
  { value: 145, label: "XL" },
];

export const SUB_FONTS: Array<{ value: SubStyle["font"]; label: string; stack: string }> = [
  { value: "sans", label: "Sans", stack: "system-ui, -apple-system, Helvetica, sans-serif" },
  { value: "serif", label: "Serif", stack: "Georgia, 'Times New Roman', serif" },
  { value: "mono", label: "Mono", stack: "ui-monospace, SFMono-Regular, Menlo, monospace" },
];

/**
 * Where the cues sit, as a WebVTT `line` percentage down the picture.
 * Null leaves the player's own placement, which is the bottom.
 */
export const SUB_PLACES: Array<{ value: SubStyle["place"]; label: string; line: number | null }> = [
  { value: "bottom", label: "Bottom", line: null },
  { value: "raised", label: "Raised", line: 78 },
  { value: "top", label: "Top", line: 8 },
];

/**
 * How many videos one "Download all" may queue. All subscriptions can be
 * hundreds of videos, which is not something to set going by accident.
 */
export const BULK_LIMITS: Array<{ value: number; label: string }> = [
  { value: 5, label: "5 videos" },
  { value: 10, label: "10 videos" },
  { value: 25, label: "25 videos" },
  { value: 50, label: "50 videos" },
  { value: 100, label: "100 videos" },
  { value: 0, label: "No limit" },
];
export const DEFAULT_BULK_LIMIT = 25;

/** Preferred subtitle language: shown when available, and downloaded. */
/** On by default: "None" means no captions anywhere, which is rarely wanted. */
export const DEFAULT_SUB_LANG = "en";

export const SUB_LANGS: Array<{ value: string; label: string }> = [
  { value: "off", label: "Off — pick per video" },
  { value: "en", label: "English" },
  { value: "nl", label: "Nederlands" },
  { value: "de", label: "Deutsch" },
  { value: "fr", label: "Français" },
  { value: "es", label: "Español" },
  { value: "it", label: "Italiano" },
  { value: "pt", label: "Português" },
];

export interface UpdateStatus {
  current: string | null;
  latest: string | null;
  up_to_date: boolean;
}
