// Channel manager (subscribed + discovery), the channel About/detail page, ephemeral exploration
// of un-subscribed channels, and the per-user channel blocklist. Only touches core's req.
import { req } from "./core";

interface ChannelLink {
  title: string | null;
  url: string;
}

export interface ChannelDetail {
  id: string;
  title: string | null;
  handle: string | null;
  description: string | null;
  thumbnail_url: string | null;
  banner_url: string | null;
  subscriber_count: number | null;
  video_count: number | null;
  total_view_count: number | null;
  published_at: string | null;
  external_links: ChannelLink[];
  country: string | null;
  default_language: string | null;
  topic_categories: string[];
  keywords: string | null;
  subscribed: boolean;
  explored: boolean;
  blocked: boolean;
  stored_videos: number;
  deep_requested: boolean;
  backfill_done: boolean;
  from_explore: boolean;
  details_synced: boolean;
  tag_ids: number[];
}

export interface ExploreResult {
  channel_id: string;
  ingested: number;
  next_page_token: string | null;
}

export interface MyStatus {
  channels_total: number;
  channels_details_synced: number;
  channels_recent_synced: number;
  channels_deep_done: number;
  channels_recent_pending: number;
  channels_deep_pending: number;
  channels_deep_requested: number;
  deep_pending_count: number;
  deep_eta_seconds: number;
  my_videos: number;
  total_videos: number;
  quota_used_today: number;
  quota_remaining_today: number;
  paused: boolean;
  sync_active: boolean; // a channel-sync job (backfill/rss) is running right now
}

export interface ManagedChannel {
  id: string;
  title: string | null;
  handle: string | null;
  thumbnail_url: string | null;
  subscriber_count: number | null;
  video_count: number | null;
  description: string | null;
  stored_videos: number;
  last_video_at: string | null;
  total_duration_seconds: number;
  count_normal: number;
  count_short: number;
  count_live: number;
  priority: number;
  hidden: boolean;
  deep_requested: boolean;
  deep_in_queue: boolean;
  tag_ids: number[];
  details_synced: boolean;
  recent_synced: boolean;
  backfill_done: boolean;
}

// A channel that shows up in the user's playlists but that they don't subscribe to —
// surfaced in the Channel manager's Discovery tab so they can subscribe in one click.
export interface DiscoveredChannel {
  id: string;
  title: string | null;
  handle: string | null;
  thumbnail_url: string | null;
  subscriber_count: number | null;
  video_count: number | null;
  description: string | null;
  playlist_video_count: number; // how many of the user's playlist videos are from here
  playlist_count: number; // across how many of their playlists
  details_synced: boolean;
}

export const channelsApi = {
  myStatus: (): Promise<MyStatus> => req("/api/sync/my-status"),
  channels: (): Promise<ManagedChannel[]> => req("/api/channels"),
  updateChannel: (
    id: string,
    patch: { priority?: number; hidden?: boolean; deep_requested?: boolean },
  ) => req(`/api/channels/${id}`, { method: "PATCH", body: JSON.stringify(patch) }),
  resetChannelBackfill: (id: string) =>
    req(`/api/channels/${id}/reset-backfill`, { method: "POST" }),
  deepAll: (on = true): Promise<{ updated: number; deep_requested: boolean }> =>
    req(`/api/sync/deep-all?on=${on}`, { method: "POST" }),
  attachChannelTag: (id: string, tagId: number) =>
    req(`/api/channels/${id}/tags`, { method: "POST", body: JSON.stringify({ tag_id: tagId }) }),
  detachChannelTag: (id: string, tagId: number) =>
    req(`/api/channels/${id}/tags/${tagId}`, { method: "DELETE" }),
  unsubscribeChannel: (id: string) => req(`/api/channels/${id}/subscription`, { method: "DELETE" }),
  discoveredChannels: (): Promise<DiscoveredChannel[]> => req("/api/channels/discovery"),
  subscribeChannel: (id: string) => req(`/api/channels/${id}/subscribe`, { method: "POST" }),
  // --- channel page (About detail + ephemeral exploration of un-subscribed channels) ---
  channelDetail: (id: string): Promise<ChannelDetail> => req(`/api/channels/${id}`),
  // Open an un-subscribed channel for browsing: ingest a page of its uploads (newest-first,
  // marked via_explore) + record the exploration. `pageToken` continues into older uploads
  // ("load more"). `quiet` so a quota-reserve 429 / load error renders inline on the page.
  exploreChannel: (id: string, pageToken?: string | null): Promise<ExploreResult> => {
    const p = new URLSearchParams();
    if (pageToken) p.set("page_token", pageToken);
    const qs = p.toString();
    return req(
      `/api/channels/${id}/explore${qs ? `?${qs}` : ""}`,
      { method: "POST" },
      { quiet: true },
    );
  },
  // --- per-user channel blocklist (excluded from live search + feed/explore) ---
  blockedChannels: (): Promise<
    { id: string; title: string | null; handle: string | null; thumbnail_url: string | null }[]
  > => req("/api/channels/blocked/list"),
  blockChannel: (id: string) => req(`/api/channels/${id}/block`, { method: "POST" }),
  unblockChannel: (id: string) => req(`/api/channels/${id}/block`, { method: "DELETE" }),
};
