"use client";

import React, { createContext, useContext, useEffect, useState, useRef } from "react";
import { useRouter } from "next/navigation";
import Button from "@/components/ui/Button";
import { AlertTriangle } from "lucide-react";

interface UnsavedChangesContextType {
  registerGuard: (enabled: boolean, onSave: (() => Promise<boolean>) | null) => void;
  triggerGuard: (targetUrl: string) => void;
}

const UnsavedChangesContext = createContext<UnsavedChangesContextType | null>(null);

export function UnsavedChangesProvider({ children }: { children: React.ReactNode }) {
  const router = useRouter();
  const [enabled, setEnabled] = useState(false);
  const onSaveRef = useRef<(() => Promise<boolean>) | null>(null);
  
  const [targetUrl, setTargetUrl] = useState<string | null>(null);
  const [showModal, setShowModal] = useState(false);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const registerGuard = (isEnabled: boolean, saveFn: (() => Promise<boolean>) | null) => {
    setEnabled(isEnabled);
    onSaveRef.current = saveFn;
  };

  const triggerGuard = (url: string) => {
    if (enabled) {
      setTargetUrl(url);
      setShowModal(true);
      setError(null);
    } else {
      router.push(url);
    }
  };

  useEffect(() => {
    function beforeUnload(e: BeforeUnloadEvent) {
      if (!enabled) return;
      e.preventDefault();
      e.returnValue = "";
    }

    function beforeInternalNavigation(e: MouseEvent) {
      if (!enabled || e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {
        return;
      }
      const target = e.target as HTMLElement | null;
      const anchor = target?.closest("a[href]") as HTMLAnchorElement | null;
      if (!anchor || anchor.target === "_blank") return;

      const next = new URL(anchor.href, window.location.href);
      if (next.origin !== window.location.origin) return;
      if (next.pathname === window.location.pathname && next.search === window.location.search) return;

      // Interceptamos la navegación interna de Next.js
      e.preventDefault();
      e.stopPropagation();
      triggerGuard(anchor.href);
    }

    window.addEventListener("beforeunload", beforeUnload);
    document.addEventListener("click", beforeInternalNavigation, true);
    return () => {
      window.removeEventListener("beforeunload", beforeUnload);
      document.removeEventListener("click", beforeInternalNavigation, true);
    };
  }, [enabled]);

  const handleDiscard = () => {
    setShowModal(false);
    setEnabled(false); // Deshabilitamos temporalmente el guardián para permitir la redirección
    if (targetUrl) {
      router.push(targetUrl);
    }
    setTargetUrl(null);
  };

  const handleSave = async () => {
    if (onSaveRef.current) {
      setSaving(true);
      setError(null);
      try {
        const success = await onSaveRef.current();
        if (success !== false) {
          setShowModal(false);
          setEnabled(false); // Deshabilitamos temporalmente el guardián para permitir la redirección
          if (targetUrl) {
            router.push(targetUrl);
          }
          setTargetUrl(null);
        } else {
          setError("No se pudieron guardar los cambios.");
        }
      } catch (err) {
        setError((err as Error).message || "Error al guardar los cambios.");
      } finally {
        setSaving(false);
      }
    } else {
      handleDiscard();
    }
  };

  const handleCancel = () => {
    setShowModal(false);
    setTargetUrl(null);
  };

  return (
    <UnsavedChangesContext.Provider value={{ registerGuard, triggerGuard }}>
      {children}
      {showModal && (
        <div className="fixed inset-0 z-[100] grid place-items-center bg-black/45 p-4" onClick={handleCancel}>
          <div 
            className="bg-surface rounded-2xl border border-line p-6 max-w-md w-full shadow-2xl flex flex-col gap-4 text-ink relative"
            onClick={(e) => e.stopPropagation()}
          >
            <div className="flex items-start gap-3">
              <div className="p-2 bg-amber-50 rounded-xl text-amber-600 border border-amber-100 flex-shrink-0">
                <AlertTriangle size={24} />
              </div>
              <div>
                <h3 className="text-lg font-bold text-ink">Cambios sin guardar</h3>
                <p className="text-sm text-ink-soft mt-1">
                  ¿Qué deseas hacer con las modificaciones realizadas?
                </p>
              </div>
            </div>

            {error && (
              <p className="text-xs text-bad bg-red-50 border border-red-200 p-2 rounded-lg font-medium">
                {error}
              </p>
            )}

            <div className="flex flex-col gap-2 mt-2">
              <Button type="button" onClick={handleSave} loading={saving} className="w-full h-11 justify-center">
                Guardar cambios
              </Button>
              <Button type="button" variant="secondary" onClick={handleDiscard} className="w-full h-11 justify-center text-amber-800 border-amber-200 bg-amber-50 hover:bg-amber-100">
                Descartar cambios
              </Button>
              <Button type="button" variant="ghost" onClick={handleCancel} className="w-full h-11 justify-center border border-line text-ink-soft hover:bg-line/20">
                Cancelar
              </Button>
            </div>
          </div>
        </div>
      )}
    </UnsavedChangesContext.Provider>
  );
}

export function useUnsavedChangesGuard(enabled: boolean, onSave?: (() => Promise<unknown>) | null) {
  const context = useContext(UnsavedChangesContext);
  if (!context) {
    throw new Error("useUnsavedChangesGuard must be used within an UnsavedChangesProvider");
  }

  useEffect(() => {
    const saveFn = onSave 
      ? async () => {
          const res = await onSave();
          return res !== false;
        }
      : null;
    
    context.registerGuard(enabled, saveFn);
    return () => {
      context.registerGuard(false, null);
    };
  }, [enabled, onSave, context]);

  return context.triggerGuard;
}
