/**
 * YouTube client that delegates to the youtube-worker sidecar container.
 * The sidecar runs youtubei.js in a full Node.js environment without
 * CPU time limits.
 */

const WORKER_URL =
  Deno.env.get("YOUTUBE_WORKER_URL") || "http://youtube-worker:3001";

export interface PlaylistItem {
  videoId: string;
  title: string;
  author: string | null;
  durationSeconds: number;
  thumbnailUrl: string | null;
}

export interface PlaylistInfo {
  title: string;
  items: PlaylistItem[];
}

export interface DownloadResult {
  storagePath: string;
  publicUrl: string;
}

async function workerFetch<T>(
  path: string,
  body: Record<string, unknown>
): Promise<T> {
  const res = await fetch(`${WORKER_URL}${path}`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });

  const data = await res.json();

  if (!res.ok) {
    throw new Error(data.error || `Worker responded with ${res.status}`);
  }

  return data as T;
}

/**
 * Parses a YouTube playlist ID from various URL formats.
 */
export function parsePlaylistId(url: string): string {
  if (/^[A-Za-z0-9_-]+$/.test(url) && !url.includes(".")) {
    return url;
  }

  try {
    const parsed = new URL(url);
    const listParam = parsed.searchParams.get("list");
    if (listParam) {
      return listParam;
    }
  } catch {
    // Not a valid URL
  }

  throw new Error(
    `Could not parse playlist ID from: "${url}". ` +
      `Expected a YouTube playlist URL or raw playlist ID.`
  );
}

/**
 * Fetches playlist metadata and items via the sidecar.
 */
export async function getPlaylistItems(
  playlistUrl: string
): Promise<PlaylistInfo> {
  return workerFetch<PlaylistInfo>("/playlist", { playlistUrl });
}

/**
 * Downloads audio and uploads to Supabase Storage via the sidecar.
 * Returns the storage path and public URL.
 */
export async function downloadAndUploadAudio(
  videoId: string,
  jobId: string
): Promise<DownloadResult> {
  return workerFetch<DownloadResult>("/download", { videoId, jobId });
}

export interface ClassifyInput {
  videoId: string;
  title: string;
  author: string | null;
}

interface ClassifyResult {
  genres: Record<string, string>;
  warning?: string;
}

/**
 * Classifies tracks into music genres via YouTube metadata + Gemini LLM.
 * Best-effort: returns empty object on failure (never throws).
 */
export async function classifyGenres(
  items: ClassifyInput[]
): Promise<Record<string, string>> {
  try {
    const result = await workerFetch<ClassifyResult>("/classify", { items });
    if (result.warning) {
      console.warn("Genre classification warning:", result.warning);
    }
    return result.genres ?? {};
  } catch (err) {
    console.error("Genre classification failed:", err);
    return {};
  }
}
