import { createWriteStream, existsSync, mkdirSync } from "node:fs";
import { join } from "node:path";
import { pipeline } from "node:stream/promises";
import { Readable } from "node:stream";
import { getDb } from "@/lib/db";

const THUMB_DIR = join(process.cwd(), "public", "thumbs");

function extFromUrl(url: string) {
  const m = url.match(/\.(jpe?g|png|webp|gif)(\?|$)/i);
  return (m?.[1] ?? "jpg").toLowerCase().replace("jpeg", "jpg");
}

export async function mirrorThumb(gameId: string, remoteUrl: string): Promise<string | null> {
  if (!remoteUrl?.startsWith("http")) return null;
  mkdirSync(THUMB_DIR, { recursive: true });
  const ext = extFromUrl(remoteUrl);
  const file = `${gameId}.${ext}`;
  const disk = join(THUMB_DIR, file);
  const web = `/thumbs/${file}`;
  if (existsSync(disk)) return web;

  try {
    const res = await fetch(remoteUrl, {
      headers: { "user-agent": "Mozilla/5.0", accept: "image/*" },
      signal: AbortSignal.timeout(25_000),
    });
    if (!res.ok || !res.body) return null;
    await pipeline(Readable.fromWeb(res.body as never), createWriteStream(disk));
    return web;
  } catch {
    return null;
  }
}

export async function mirrorThumbsBatch(limit = 50_000, offset = 0): Promise<{ done: number; failed: number }> {
  const db = getDb();
  const rows = db
    .prepare(
      `SELECT id, thumb_url FROM games WHERE thumb_local IS NULL OR thumb_local = '' ORDER BY created_at LIMIT ? OFFSET ?`,
    )
    .all(limit, offset) as { id: string; thumb_url: string }[];

  const upd = db.prepare(`UPDATE games SET thumb_local = ? WHERE id = ?`);
  let done = 0;
  let failed = 0;

  for (const row of rows) {
    const local = await mirrorThumb(row.id, row.thumb_url);
    if (local) {
      upd.run(local, row.id);
      done++;
    } else failed++;
  }
  return { done, failed };
}

export function resolveThumb(row: { thumb_url: string; thumb_local?: string | null }) {
  return row.thumb_local || row.thumb_url;
}
