import { useAuth } from "@/_core/hooks/useAuth";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { trpc } from "@/lib/trpc";
import { cn } from "@/lib/utils";
import { HelpCircle, Sparkles, X } from "lucide-react";
import { useEffect, useMemo, useRef, useState } from "react";
import { useLocation } from "wouter";

type OperatingTourAudience = "association" | "accueil" | "admin";

type OperatingTourStep = {
  id: string;
  route: string;
  selector: string;
  title: string;
  description: string;
};

const STEP_GROUPS: Record<OperatingTourAudience, OperatingTourStep[]> = {
  association: [
    {
      id: "association-dashboard",
      route: "/dashboard",
      selector: '[data-tour-id="dashboard-welcome"]',
      title: "Tableau de bord association",
      description: "C’est votre point de départ. Vous y retrouvez les raccourcis, vos documents et l’état général de vos démarches.",
    },
    {
      id: "association-profile-nav",
      route: "/dashboard",
      selector: '[data-tour-id="nav-profile"]',
      title: "Mettre à jour la fiche",
      description: "Passez ici pour compléter ou corriger la fiche de votre association avant d’envoyer de nouvelles demandes.",
    },
    {
      id: "association-profile-page",
      route: "/dashboard/profile",
      selector: '[data-tour-id="profile-header"]',
      title: "Page Mon association",
      description: "Cette page centralise l’identité de l’association, ses coordonnées et les informations utiles à l’administration.",
    },
    {
      id: "association-documents",
      route: "/dashboard/documents",
      selector: '[data-tour-id="documents-header"]',
      title: "Déposer les documents",
      description: "Ajoutez ici les pièces demandées comme le RIB, les statuts ou l’attestation d’assurance pour éviter les blocages.",
    },
    {
      id: "association-requests",
      route: "/dashboard/requests",
      selector: '[data-tour-id="requests-new"]',
      title: "Créer une nouvelle demande",
      description: "Depuis Mes demandes, vous lancez un nouveau dossier et vous suivez ensuite son état sans perdre le fil.",
    },
    {
      id: "association-reservation",
      route: "/dashboard/reservation-salle",
      selector: '[data-tour-id="reservation-header"]',
      title: "Réserver une salle",
      description: "Le formulaire guide la réservation pas à pas, avec les créneaux, les dates et les salles nécessaires.",
    },
    {
      id: "association-directory",
      route: "/dashboard/associations",
      selector: '[data-tour-id="directory-header"]',
      title: "Consulter l’annuaire",
      description: "L’annuaire permet de retrouver rapidement une association, vérifier sa visibilité et partager les bonnes informations.",
    },
  ],
  accueil: [
    {
      id: "accueil-admin-home",
      route: "/admin",
      selector: '[data-tour-id="admin-header"]',
      title: "Accueil administratif",
      description: "Cette vue vous remet sur les priorités du jour et les chemins rapides vers les dossiers à faire avancer.",
    },
    {
      id: "accueil-requests",
      route: "/admin?tab=requests",
      selector: '[data-tour-id="admin-tab-requests"]',
      title: "Gestion des demandes",
      description: "C’est ici que l’hôtesse traite les demandes entrantes, suit les devis et relance les dossiers en attente.",
    },
    {
      id: "accueil-calendar",
      route: "/admin?tab=calendrier",
      selector: '[data-tour-id="admin-tab-calendrier"]',
      title: "Calendrier",
      description: "Le calendrier aide à vérifier les disponibilités et à éviter les conflits avant validation.",
    },
    {
      id: "accueil-notifications",
      route: "/admin?tab=notifications",
      selector: '[data-tour-id="admin-tab-notifications"]',
      title: "Notifications",
      description: "Les alertes et retours importants arrivent ici pour que rien ne reste silencieusement bloqué.",
    },
  ],
  admin: [
    {
      id: "admin-home",
      route: "/admin",
      selector: '[data-tour-id="admin-header"]',
      title: "Vue d’administration",
      description: "Vous retrouvez ici les modules globaux, les états de supervision et l’accès rapide aux réglages sensibles.",
    },
    {
      id: "admin-requests",
      route: "/admin?tab=requests",
      selector: '[data-tour-id="admin-tab-requests"]',
      title: "Pilotage des demandes",
      description: "Cet onglet concentre le suivi des dossiers, les arbitrages et les points qui demandent une action rapide.",
    },
    {
      id: "admin-analytics",
      route: "/admin?tab=analytics",
      selector: '[data-tour-id="admin-tab-analytics"]',
      title: "Statistiques et supervision",
      description: "Vous y trouvez le Double Tour opérationnel, les indicateurs clés et le suivi technique du portail.",
    },
    {
      id: "admin-ccds-directory",
      route: "/admin?tab=ccds-directory",
      selector: '[data-tour-id="admin-tab-ccds-directory"]',
      title: "Annuaire interne CCDS",
      description: "Cet espace regroupe le répertoire interne et les informations utiles aux équipes pour travailler plus vite.",
    },
  ],
};

function getAudience(role: string | undefined): OperatingTourAudience | null {
  if (role === "user") return "association";
  if (role === "accueil") return "accueil";
  if (role === "admin" || role === "super_admin" || role === "directrice" || role === "logistique_controle") {
    return "admin";
  }
  return null;
}

function clamp(value: number, min: number, max: number) {
  return Math.min(Math.max(value, min), max);
}

export function UserOperatingTour() {
  const { user } = useAuth();
  const [, setLocation] = useLocation();
  const { data: settings } = trpc.settings.getUserOperatingTour.useQuery();
  const [isOpen, setIsOpen] = useState(false);
  const [stepIndex, setStepIndex] = useState(0);
  const [targetRect, setTargetRect] = useState<DOMRect | null>(null);
  const [selectorReady, setSelectorReady] = useState(false);
  const lastScrolledStepRef = useRef<string | null>(null);
  const audience = getAudience(user?.role);

  const steps = useMemo(() => (audience ? STEP_GROUPS[audience] : []), [audience]);
  const activeStep = steps[stepIndex] || null;

  useEffect(() => {
    if (!settings?.enabled) {
      setIsOpen(false);
    }
  }, [settings?.enabled]);

  useEffect(() => {
    if (!audience) {
      setIsOpen(false);
      setStepIndex(0);
    }
  }, [audience]);

  useEffect(() => {
    if (!isOpen || !activeStep) return;

    let cancelled = false;
    let timer: number | null = null;

    const updateRect = () => {
      const node = document.querySelector(activeStep.selector);
      if (node instanceof HTMLElement) {
        setSelectorReady(true);
        setTargetRect(node.getBoundingClientRect());
      } else {
        setSelectorReady(false);
        setTargetRect(null);
      }
    };

    const syncStep = (attempt = 0) => {
      if (cancelled) return;

      const currentRoute = `${window.location.pathname}${window.location.search}`;
      if (currentRoute !== activeStep.route) {
        setSelectorReady(false);
        setTargetRect(null);
        setLocation(activeStep.route);
        timer = window.setTimeout(() => syncStep(attempt + 1), attempt > 3 ? 280 : 120);
        return;
      }

      const node = document.querySelector(activeStep.selector);
      if (node instanceof HTMLElement) {
        if (lastScrolledStepRef.current !== activeStep.id) {
          node.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
          lastScrolledStepRef.current = activeStep.id;
        }
        setSelectorReady(true);
        setTargetRect(node.getBoundingClientRect());
        return;
      }

      if (attempt < 30) {
        timer = window.setTimeout(() => syncStep(attempt + 1), 180);
      } else {
        setSelectorReady(false);
        setTargetRect(null);
      }
    };

    syncStep();
    window.addEventListener("resize", updateRect);
    window.addEventListener("scroll", updateRect, true);

    return () => {
      cancelled = true;
      if (timer) {
        window.clearTimeout(timer);
      }
      window.removeEventListener("resize", updateRect);
      window.removeEventListener("scroll", updateRect, true);
    };
  }, [activeStep, isOpen, setLocation]);

  if (!settings?.enabled || !audience || steps.length === 0) {
    return null;
  }

  const startTour = () => {
    lastScrolledStepRef.current = null;
    setStepIndex(0);
    setIsOpen(true);
  };

  const stopTour = () => {
    setIsOpen(false);
    setTargetRect(null);
    setSelectorReady(false);
  };

  const goNext = () => {
    if (stepIndex >= steps.length - 1) {
      stopTour();
      return;
    }
    setStepIndex((current) => current + 1);
  };

  const goPrevious = () => {
    setStepIndex((current) => Math.max(0, current - 1));
  };

  const bubbleWidth = typeof window === "undefined" ? 360 : Math.min(360, window.innerWidth - 32);
  const bubbleHeightEstimate = 220;
  const bubbleLeft = targetRect
    ? clamp(targetRect.left, 16, Math.max(16, window.innerWidth - bubbleWidth - 16))
    : Math.max(16, (typeof window !== "undefined" ? window.innerWidth : 420) / 2 - bubbleWidth / 2);
  const bubbleTop = targetRect
    ? targetRect.top > (window.innerHeight * 0.55)
      ? clamp(targetRect.top - bubbleHeightEstimate - 16, 16, Math.max(16, window.innerHeight - bubbleHeightEstimate - 16))
      : clamp(targetRect.bottom + 16, 16, Math.max(16, window.innerHeight - bubbleHeightEstimate - 16))
    : Math.max(24, (typeof window !== "undefined" ? window.innerHeight : 720) / 2 - bubbleHeightEstimate / 2);

  return (
    <>
      <div className="fixed bottom-5 right-5 z-[90] flex items-center gap-2">
        <Badge variant="outline" className="border-primary/30 bg-white/95 px-3 py-2 shadow-sm">
          <Sparkles className="h-3.5 w-3.5 text-primary" />
          Tour guide
        </Badge>
        <Button
          type="button"
          size="sm"
          onClick={isOpen ? stopTour : startTour}
          className="shadow-lg"
        >
          <HelpCircle className="mr-2 h-4 w-4" />
          {isOpen ? "Arreter le tour" : "Lancer le tour"}
        </Button>
      </div>

      {isOpen ? (
        <div className="pointer-events-none fixed inset-0 z-[85]">
          {targetRect ? (
            <>
              <div className="absolute left-0 top-0 w-full bg-slate-950/55" style={{ height: Math.max(0, targetRect.top - 8) }} />
              <div className="absolute left-0 bg-slate-950/55" style={{ top: Math.max(0, targetRect.top - 8), width: Math.max(0, targetRect.left - 8), height: targetRect.height + 16 }} />
              <div className="absolute right-0 bg-slate-950/55" style={{ top: Math.max(0, targetRect.top - 8), left: targetRect.right + 8, height: targetRect.height + 16 }} />
              <div className="absolute left-0 w-full bg-slate-950/55" style={{ top: targetRect.bottom + 8, bottom: 0 }} />
              <div
                className="absolute rounded-xl border-2 border-primary bg-white/10 shadow-[0_0_0_9999px_rgba(15,23,42,0.04)] transition-all"
                style={{
                  left: targetRect.left - 8,
                  top: targetRect.top - 8,
                  width: targetRect.width + 16,
                  height: targetRect.height + 16,
                }}
              />
            </>
          ) : (
            <div className="absolute inset-0 bg-slate-950/55" />
          )}

          <div
            className={cn(
              "pointer-events-auto fixed rounded-xl border bg-white p-4 shadow-2xl",
              selectorReady ? "border-primary/30" : "border-amber-200"
            )}
            style={{ width: bubbleWidth, left: bubbleLeft, top: bubbleTop }}
          >
            <div className="flex items-start justify-between gap-3">
              <div className="space-y-1">
                <Badge variant="outline" className="border-primary/20 bg-primary/5 text-primary">
                  Etape {stepIndex + 1} sur {steps.length}
                </Badge>
                <h3 className="text-base font-semibold">{activeStep?.title}</h3>
              </div>
              <Button type="button" size="icon" variant="ghost" className="h-8 w-8 shrink-0" onClick={stopTour}>
                <X className="h-4 w-4" />
              </Button>
            </div>
            <p className="mt-3 text-sm leading-6 text-muted-foreground">
              {selectorReady
                ? activeStep?.description
                : "Je prepare cette etape et je me place sur le bon ecran pour te la montrer proprement."}
            </p>
            <div className="mt-4 flex flex-wrap items-center justify-between gap-2">
              <Button type="button" variant="ghost" size="sm" onClick={stopTour}>
                Fermer
              </Button>
              <div className="flex flex-wrap gap-2">
                <Button type="button" variant="outline" size="sm" onClick={goPrevious} disabled={stepIndex === 0}>
                  Retour
                </Button>
                <Button type="button" size="sm" onClick={goNext}>
                  {stepIndex >= steps.length - 1 ? "Terminer" : "Suivant"}
                </Button>
              </div>
            </div>
          </div>
        </div>
      ) : null}
    </>
  );
}

export default UserOperatingTour;
