import { createServerFn } from "@tanstack/react-start";
import { z } from "zod";
import { createHash, timingSafeEqual } from "node:crypto";

function checkPassword(input: string) {
  const expected = process.env["ADMIN_PASSWORD"];
  if (!expected) throw new Error("Admin-wachtwoord is niet ingesteld");
  const a = createHash("sha256").update(input, "utf8").digest();
  const b = createHash("sha256").update(expected, "utf8").digest();
  if (!timingSafeEqual(a, b)) throw new Error("Onjuist wachtwoord");
}

const filmSchema = z.object({
  titel: z.string().trim().min(1).max(200),
  beschrijving: z.string().trim().max(2000),
  genre: z.string().trim().max(60),
  jaar: z.number().int().min(1880).max(2100).nullable(),
  cover_url: z.string().trim().max(1000),
  video_url: z.string().trim().max(1000),
});

export const verifyAdmin = createServerFn({ method: "POST" })
  .inputValidator((d) => z.object({ password: z.string().max(200) }).parse(d))
  .handler(async ({ data }) => {
    try {
      checkPassword(data.password);
      return { ok: true };
    } catch {
      return { ok: false };
    }
  });

export const saveFilm = createServerFn({ method: "POST" })
  .inputValidator((d) =>
    z
      .object({ password: z.string().max(200), id: z.string().uuid().optional(), film: filmSchema })
      .parse(d),
  )
  .handler(async ({ data }) => {
    checkPassword(data.password);
    const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
    const { fetchMovieMeterActors } = await import("./moviemeter-cast.server");
    let acteurs: string[] | undefined;
    try {
      acteurs = await fetchMovieMeterActors(data.film.titel, data.film.jaar);
    } catch {
      acteurs = undefined; // keep existing actors when MovieMeter is unreachable
    }
    const row = acteurs && acteurs.length ? { ...data.film, acteurs } : data.film;
    const q = data.id
      ? supabaseAdmin.from("films").update(row).eq("id", data.id)
      : supabaseAdmin.from("films").insert(row);
    const { error } = await q;
    if (error) throw new Error("Opslaan mislukt");
    return { ok: true, acteurs: acteurs?.length ?? 0 };
  });

export const importAllActors = createServerFn({ method: "POST" })
  .inputValidator((d) => z.object({ password: z.string().max(200) }).parse(d))
  .handler(async ({ data }) => {
    checkPassword(data.password);
    const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
    const { fetchMovieMeterActors } = await import("./moviemeter-cast.server");
    const { data: films, error } = await supabaseAdmin.from("films").select("id, titel, jaar");
    if (error) throw new Error("Films ophalen mislukt");
    let found = 0;
    for (const f of films ?? []) {
      try {
        const acteurs = await fetchMovieMeterActors(f.titel, f.jaar);
        if (acteurs.length) {
          await supabaseAdmin.from("films").update({ acteurs }).eq("id", f.id);
          found++;
        }
      } catch {
        // skip films MovieMeter could not return
      }
    }
    return { found, total: films?.length ?? 0 };
  });

export const deleteFilm = createServerFn({ method: "POST" })
  .inputValidator((d) => z.object({ password: z.string().max(200), id: z.string().uuid() }).parse(d))
  .handler(async ({ data }) => {
    checkPassword(data.password);
    const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
    const { error } = await supabaseAdmin.from("films").delete().eq("id", data.id);
    if (error) throw new Error("Verwijderen mislukt");
    return { ok: true };
  });
