"use client";
import { useEffect, useRef, useState } from "react";
import type { EnquiryAction } from "@/lib/contact-schema";
type TurnstileApi = {
  render(
    container: HTMLElement,
    options: {
      sitekey: string;
      action: string;
      callback: (token: string) => void;
      "expired-callback": () => void;
      "error-callback": () => void;
    },
  ): string;
  remove(id: string): void;
};
declare global {
  interface Window {
    turnstile?: TurnstileApi;
  }
}
let scriptLoad: Promise<void> | undefined;
function loadScript() {
  if (window.turnstile) return Promise.resolve();
  if (!scriptLoad)
    scriptLoad = new Promise<void>((resolve, reject) => {
      const script = document.createElement("script");
      script.src =
        "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
      script.async = true;
      const fail = () => {
        clearTimeout(timer);
        script.remove();
        scriptLoad = undefined;
        reject(new Error("Security check unavailable"));
      };
      const timer = setTimeout(fail, 15000);
      script.onload = () => {
        clearTimeout(timer);
        if (window.turnstile) resolve();
        else fail();
      };
      script.onerror = fail;
      document.head.append(script);
    });
  return scriptLoad;
}
type TurnstileAction = EnquiryAction | "application";
const previewNotes: Record<TurnstileAction, string> = {
  contact: "enquiries are not sent.",
  "quick-apply": "requests are not sent.",
  application: "applications use isolated test storage.",
};
export function Turnstile({
  siteKey,
  mock,
  resetKey,
  onToken,
  action = "contact",
}: {
  siteKey?: string;
  mock: boolean;
  resetKey: number;
  onToken: (token: string) => void;
  action?: TurnstileAction;
}) {
  const container = useRef<HTMLDivElement>(null);
  const [failed, setFailed] = useState(false);
  const [attempt, setAttempt] = useState(0);
  useEffect(() => {
    if (mock) {
      onToken(`mock-${action}-verification`);
      return;
    }
    if (!siteKey) {
      onToken(`${action}-unchallenged`);
      return;
    }
    let active = true,
      id: string | undefined;
    loadScript()
      .then(() => {
        if (!active || !container.current || !siteKey) return;
        id = window.turnstile?.render(container.current, {
          sitekey: siteKey,
          action,
          callback: (token) => {
            if (active) {
              setFailed(false);
              onToken(token);
            }
          },
          "expired-callback": () => {
            if (active) onToken("");
          },
          "error-callback": () => {
            if (active) {
              onToken("");
              setFailed(true);
            }
          },
        });
      })
      .catch(() => {
        if (active) setFailed(true);
      });
    return () => {
      active = false;
      if (id) window.turnstile?.remove(id);
    };
  }, [siteKey, mock, resetKey, attempt, onToken, action]);
  return (
    <div className="turnstile-space">
      <div ref={container} />
      {mock && <p>Preview mode: {previewNotes[action]}</p>}
      {failed && (
        <p role="alert">
          Security check unavailable.{" "}
          <button
            type="button"
            onClick={() => {
              setFailed(false);
              onToken("");
              setAttempt((n) => n + 1);
            }}
          >
            Try again
          </button>
        </p>
      )}
    </div>
  );
}
