"use client";

import { useCallback, useEffect, useRef, useState, type ReactNode } from "react";

type ConfirmationTone = "default" | "danger";

type ConfirmationRequest = {
  title: string;
  message: string;
  confirmLabel: string;
  tone: ConfirmationTone;
  onConfirm: () => void;
};

const confirmationVerbs = /\b(enregistrer|créer|ajouter|mettre à jour|modifier|valider|approuver|refuser|supprimer|clôturer|exécuter|transmettre|soumettre|affecter|classer|archiver|réceptionner)\b/i;
const destructiveVerbs = /\b(supprimer|refuser|annuler|clôturer|archiver|sortie|retirer)\b/i;
const leaveLabels = /^(×|fermer|annuler|quitter|sortir|retour(?:\s|$)|revenir(?:\s|$))/i;

function normalizedLabel(element: HTMLElement | null) {
  if (!element) return "";
  return (element.getAttribute("aria-label") || element.getAttribute("title") || element.textContent || "")
    .replace(/\s+/g, " ")
    .trim();
}

function dirtyFormsFor(trigger: HTMLElement) {
  const scope = trigger.closest<HTMLElement>("[role='dialog'], .modal, .modal-card, .drawer, .inline-editor, .bank-editor, .supplier-bank-editor");
  const local = scope ? [...scope.querySelectorAll<HTMLFormElement>("form[data-moventra-dirty='true']")] : [];
  if (local.length) return local;
  if (trigger.matches(".module-tab-close, .drawer-floating-exit, [data-leave-application]")) {
    return [...document.querySelectorAll<HTMLFormElement>("form[data-moventra-dirty='true']")];
  }
  return [];
}

function formConfirmation(form: HTMLFormElement, submitter: HTMLElement | null) {
  const explicit = submitter?.getAttribute("data-confirm-message") || form.getAttribute("data-confirm-message");
  const label = normalizedLabel(submitter) || "Enregistrer";
  if (explicit) return { label, message: explicit };
  if (!confirmationVerbs.test(label)) return null;
  return {
    label,
    message: `Confirmez-vous l’action « ${label} » ? Les informations seront enregistrées et pourront modifier les données du logiciel.`,
  };
}

export function InteractionSafety({ children }: { children: ReactNode }) {
  const [request, setRequest] = useState<ConfirmationRequest | null>(null);
  const dialogRef = useRef<HTMLDivElement>(null);
  const restoreFocusRef = useRef<HTMLElement | null>(null);
  const bypassClickRef = useRef(new WeakSet<HTMLElement>());
  const bypassPointerRef = useRef(new WeakSet<HTMLElement>());

  const ask = useCallback((next: ConfirmationRequest, focusTarget?: HTMLElement | null) => {
    restoreFocusRef.current = focusTarget ?? (document.activeElement as HTMLElement | null);
    setRequest(next);
  }, []);

  const closeDialog = useCallback(() => {
    setRequest(null);
    window.setTimeout(() => restoreFocusRef.current?.focus(), 0);
  }, []);

  useEffect(() => {
    if (!request) return;
    const firstButton = dialogRef.current?.querySelector<HTMLButtonElement>("button");
    firstButton?.focus();
  }, [request]);

  useEffect(() => {
    const markDirty = (event: Event) => {
      const control = event.target instanceof HTMLElement ? event.target : null;
      const form = control?.closest<HTMLFormElement>("form");
      if (form && form.dataset.confirm !== "none") form.dataset.moventraDirty = "true";
    };

    const markClean = (event: Event) => {
      const form = event.target instanceof HTMLFormElement ? event.target : null;
      if (form) window.setTimeout(() => delete form.dataset.moventraDirty, 0);
    };

    const handleSaved = () => {
      document.querySelectorAll<HTMLFormElement>("form[data-moventra-dirty='true']").forEach((form) => delete form.dataset.moventraDirty);
    };

    const handleSubmit = (event: SubmitEvent) => {
      const form = event.target instanceof HTMLFormElement ? event.target : null;
      if (!form || form.dataset.confirm === "none" || form.dataset.moventraConfirmed === "true") {
        if (form) delete form.dataset.moventraConfirmed;
        return;
      }
      const submitter = event.submitter instanceof HTMLElement ? event.submitter : null;
      if (submitter?.dataset.confirm === "none") return;
      const confirmation = formConfirmation(form, submitter);
      if (!confirmation) return;

      event.preventDefault();
      event.stopImmediatePropagation();
      const tone: ConfirmationTone = destructiveVerbs.test(confirmation.label) ? "danger" : "default";
      ask({
        title: tone === "danger" ? "Confirmer l’action sensible" : "Confirmer l’enregistrement",
        message: confirmation.message,
        confirmLabel: confirmation.label,
        tone,
        onConfirm: () => {
          form.dataset.moventraConfirmed = "true";
          form.requestSubmit(event.submitter instanceof HTMLButtonElement || event.submitter instanceof HTMLInputElement ? event.submitter : undefined);
        },
      }, submitter);
    };

    const handleClick = (event: MouseEvent) => {
      const trigger = event.target instanceof HTMLElement ? event.target.closest<HTMLElement>("button, a") : null;
      if (!trigger || trigger.dataset.confirm === "none") return;
      if (bypassClickRef.current.delete(trigger)) return;

      const explicitMessage = trigger.dataset.confirmMessage;
      const label = normalizedLabel(trigger);
      const forms = dirtyFormsFor(trigger);
      const isLeave = trigger.dataset.leaveAction === "true" || leaveLabels.test(label);

      if (!explicitMessage && !(isLeave && forms.length)) return;
      event.preventDefault();
      event.stopImmediatePropagation();

      const message = explicitMessage || "Des modifications ne sont pas enregistrées. Voulez-vous les abandonner et quitter cet écran ?";
      const tone: ConfirmationTone = explicitMessage && destructiveVerbs.test(label) ? "danger" : "default";
      ask({
        title: explicitMessage ? (tone === "danger" ? "Confirmer l’action sensible" : "Confirmer l’action") : "Quitter sans enregistrer ?",
        message,
        confirmLabel: explicitMessage ? label || "Confirmer" : "Quitter sans enregistrer",
        tone,
        onConfirm: () => {
          forms.forEach((form) => delete form.dataset.moventraDirty);
          bypassClickRef.current.add(trigger);
          trigger.click();
        },
      }, trigger);
    };

    const handlePointerDown = (event: MouseEvent) => {
      const backdrop = event.target instanceof HTMLElement && event.target.matches(".modal-backdrop") ? event.target : null;
      if (!backdrop || bypassPointerRef.current.delete(backdrop)) return;
      const forms = [...backdrop.querySelectorAll<HTMLFormElement>("form[data-moventra-dirty='true']")];
      if (!forms.length) return;
      event.preventDefault();
      event.stopImmediatePropagation();
      ask({
        title: "Quitter sans enregistrer ?",
        message: "Des modifications ne sont pas enregistrées. Voulez-vous les abandonner et fermer cette fenêtre ?",
        confirmLabel: "Quitter sans enregistrer",
        tone: "default",
        onConfirm: () => {
          forms.forEach((form) => delete form.dataset.moventraDirty);
          bypassPointerRef.current.add(backdrop);
          backdrop.dispatchEvent(new MouseEvent("mousedown", { bubbles: true, cancelable: true, view: window }));
        },
      }, backdrop);
    };

    const handleBeforeUnload = (event: BeforeUnloadEvent) => {
      if (!document.querySelector("form[data-moventra-dirty='true']")) return;
      event.preventDefault();
      event.returnValue = "";
    };

    document.addEventListener("input", markDirty, true);
    document.addEventListener("change", markDirty, true);
    document.addEventListener("reset", markClean, true);
    document.addEventListener("submit", handleSubmit, true);
    document.addEventListener("click", handleClick, true);
    document.addEventListener("mousedown", handlePointerDown, true);
    window.addEventListener("moventra:saved", handleSaved);
    window.addEventListener("beforeunload", handleBeforeUnload);
    return () => {
      document.removeEventListener("input", markDirty, true);
      document.removeEventListener("change", markDirty, true);
      document.removeEventListener("reset", markClean, true);
      document.removeEventListener("submit", handleSubmit, true);
      document.removeEventListener("click", handleClick, true);
      document.removeEventListener("mousedown", handlePointerDown, true);
      window.removeEventListener("moventra:saved", handleSaved);
      window.removeEventListener("beforeunload", handleBeforeUnload);
    };
  }, [ask]);

  useEffect(() => {
    if (!request) return;
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === "Escape") {
        event.preventDefault();
        closeDialog();
        return;
      }
      if (event.key !== "Tab") return;
      const focusable = [...(dialogRef.current?.querySelectorAll<HTMLElement>("button, [href], input, select, textarea, [tabindex]:not([tabindex='-1'])") ?? [])];
      if (!focusable.length) return;
      const first = focusable[0];
      const last = focusable[focusable.length - 1];
      if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); }
      else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); }
    };
    document.addEventListener("keydown", handleKeyDown, true);
    return () => document.removeEventListener("keydown", handleKeyDown, true);
  }, [closeDialog, request]);

  return <>
    {children}
    {request && <div className="interaction-safety-backdrop" role="presentation">
      <div ref={dialogRef} className="interaction-safety-dialog" role="alertdialog" aria-modal="true" aria-labelledby="interaction-safety-title" aria-describedby="interaction-safety-message">
        <div className={`interaction-safety-icon ${request.tone}`} aria-hidden="true">{request.tone === "danger" ? "!" : "✓"}</div>
        <div>
          <h2 id="interaction-safety-title">{request.title}</h2>
          <p id="interaction-safety-message">{request.message}</p>
        </div>
        <div className="interaction-safety-actions">
          <button type="button" className="secondary-button" onClick={closeDialog}>Revenir au formulaire</button>
          <button type="button" className={request.tone === "danger" ? "danger-button" : "primary-button"} onClick={() => { const action = request.onConfirm; setRequest(null); action(); }}>
            {request.confirmLabel}
          </button>
        </div>
      </div>
    </div>}
  </>;
}
