"use client";

import { useEffect, useRef, useState } from "react";

const SCRIPTS = {
  recaptcha: "https://www.google.com/recaptcha/api.js?render=explicit",
  turnstile: "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit",
  hcaptcha: "https://js.hcaptcha.com/1/api.js?render=explicit",
} as const;

type Config = { provider: string; siteKey?: string; on?: Record<string, boolean> };

/**
 * Renders whichever challenge the admin configured, or nothing when captcha
 * is off — so a form can include it unconditionally.
 */
export function Captcha({
  action,
  onToken,
}: {
  action: "signup" | "login" | "post" | "contact";
  onToken: (token: string) => void;
}) {
  const [config, setConfig] = useState<Config | null>(null);
  const box = useRef<HTMLDivElement>(null);
  const rendered = useRef(false);

  useEffect(() => {
    fetch("/api/captcha")
      .then((r) => (r.ok ? r.json() : null))
      .then(setConfig)
      .catch(() => {});
  }, []);

  useEffect(() => {
    if (!config || config.provider === "none" || !config.siteKey) return;
    if (!config.on?.[action]) return;
    if (rendered.current || !box.current) return;

    const provider = config.provider as keyof typeof SCRIPTS;
    const src = SCRIPTS[provider];
    if (!src) return;

    // Each provider exposes a global with the same render/reset shape.
    const globalName =
      provider === "recaptcha" ? "grecaptcha" : provider === "turnstile" ? "turnstile" : "hcaptcha";

    const draw = () => {
      const api = (window as unknown as Record<string, { render?: (el: HTMLElement, opts: object) => void }>)[globalName];
      if (!api?.render || !box.current || rendered.current) return;
      rendered.current = true;
      api.render(box.current, {
        sitekey: config.siteKey,
        callback: (token: string) => onToken(token),
        "expired-callback": () => onToken(""),
      });
    };

    if (document.querySelector(`script[src="${src}"]`)) {
      // Already loading or loaded — wait for the global to appear.
      const timer = setInterval(() => {
        if ((window as unknown as Record<string, unknown>)[globalName]) {
          clearInterval(timer);
          draw();
        }
      }, 120);
      return () => clearInterval(timer);
    }

    const script = document.createElement("script");
    script.src = src;
    script.async = true;
    script.defer = true;
    script.onload = draw;
    document.head.appendChild(script);
  }, [config, action, onToken]);

  if (!config || config.provider === "none" || !config.on?.[action]) return null;

  return <div ref={box} className="cap-box" />;
}
