"use client";

import { useEffect, useMemo, useState, type CSSProperties } from "react";
import type { HomeViewportMode } from "@/components/home-viewport-shell";
import { completeDemoHomeTutorial } from "@/lib/demo-session-store";

const FULL_TUTORIAL_MIN_WIDTH = 1024;
const VIEWPORT_MARGIN = 20;
const SPOTLIGHT_PADDING = 14;
const SPOTLIGHT_FALLBACK_RADIUS = 28;
const DESKTOP_BUBBLE_WIDTH = 304;
const CENTER_BUBBLE_WIDTH = 360;
const DESKTOP_BUBBLE_OFFSET = 24;

type TutorialStepId =
  | "welcome"
  | "scenarios"
  | "filters"
  | "sidebar"
  | "coach-switch"
  | "coach-workspace"
  | "finish";

type SpotlightRect = {
  top: number;
  left: number;
  width: number;
  height: number;
  right: number;
  bottom: number;
  radius: number;
};

type TutorialStep = {
  id: TutorialStepId;
  title: string;
  description: string;
  selectors?: string[];
  primaryLabel?: string;
  backLabel?: string;
  waitingForCoachClick?: boolean;
};

const tutorialSteps: Record<TutorialStepId, TutorialStep> = {
  welcome: {
    id: "welcome",
    title: "Bienvenue sur EvolIA",
    description:
      "Ce guide montre les zones clefs de la demo: les simulations, les filtres, l'espace utilisateur et le coach.",
    primaryLabel: "Commencer",
  },
  scenarios: {
    id: "scenarios",
    title: "Les cas pratiques",
    description:
      "Ici se trouvent les simulations manageriales disponibles, avec le niveau, la competence ciblee et le contexte de chaque cas.",
    selectors: ['[data-tutorial-target="scenario-cards"]'],
    primaryLabel: "Suivant",
  },
  filters: {
    id: "filters",
    title: "Les filtres",
    description:
      "Ces filtres affichent uniquement les cas souhaites par niveau ou par tag, sans modifier le contenu de la demo.",
    selectors: ['[data-tutorial-target="scenario-filters"]'],
    primaryLabel: "Suivant",
  },
  sidebar: {
    id: "sidebar",
    title: "L'espace utilisateur",
    description:
      "Cette zone resume l'activite et les reglages. Pour la demo, l'acces est protege, l'admin est bloque, et les donnees restent dans la session navigateur pour soutenir le discours RGPD et securite.",
    selectors: ['[data-tutorial-target="user-sidebar"]'],
    primaryLabel: "Suivant",
  },
  "coach-switch": {
    id: "coach-switch",
    title: "Ouvrir le coach",
    description:
      "Cliquez maintenant sur le bouton Coach pour afficher l'espace d'accompagnement.",
    selectors: ['[data-tutorial-target="coach-tab"]'],
    waitingForCoachClick: true,
    backLabel: "Retour",
  },
  "coach-workspace": {
    id: "coach-workspace",
    title: "Le coach",
    description:
      "Le coach utilise le contexte onboarding, les rapports deja produits et la base YAML locale. La zone de saisie sert a poser une situation ou demander un appui concret.",
    selectors: [
      '[data-tutorial-target="coach-composer"]',
      '[data-tutorial-target="coach-shell"]',
    ],
    primaryLabel: "Terminer",
    backLabel: "Retour",
  },
  finish: {
    id: "finish",
    title: "C'est termine",
    description:
      "La plateforme est prete. Vous pouvez maintenant utiliser librement les simulations et le coach.",
    primaryLabel: "Entrer",
    backLabel: "Retour",
  },
};

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

function getTargetRadius(target: HTMLElement) {
  const styles = window.getComputedStyle(target);
  const radii = [
    styles.borderTopLeftRadius,
    styles.borderTopRightRadius,
    styles.borderBottomRightRadius,
    styles.borderBottomLeftRadius,
  ]
    .map((value) => Number.parseFloat(value))
    .filter((value) => Number.isFinite(value) && value > 0);

  return radii.length > 0
    ? Math.max(...radii)
    : SPOTLIGHT_FALLBACK_RADIUS;
}

function resolveSpotlightRect(selectors: string[]) {
  if (typeof window === "undefined") {
    return null;
  }

  const target = selectors
    .map((selector) => document.querySelector<HTMLElement>(selector))
    .find((element) => element !== null);

  if (!target) {
    return null;
  }

  const rawRect = target.getBoundingClientRect();
  if (rawRect.width <= 0 || rawRect.height <= 0) {
    return null;
  }

  const top = clamp(
    rawRect.top - SPOTLIGHT_PADDING,
    VIEWPORT_MARGIN,
    window.innerHeight - VIEWPORT_MARGIN,
  );
  const left = clamp(
    rawRect.left - SPOTLIGHT_PADDING,
    VIEWPORT_MARGIN,
    window.innerWidth - VIEWPORT_MARGIN,
  );
  const right = clamp(
    rawRect.right + SPOTLIGHT_PADDING,
    VIEWPORT_MARGIN,
    window.innerWidth - VIEWPORT_MARGIN,
  );
  const bottom = clamp(
    rawRect.bottom + SPOTLIGHT_PADDING,
    VIEWPORT_MARGIN,
    window.innerHeight - VIEWPORT_MARGIN,
  );

  return {
    top,
    left,
    width: Math.max(right - left, 0),
    height: Math.max(bottom - top, 0),
    right,
    bottom,
    radius: clamp(
      getTargetRadius(target) + 6,
      18,
      Math.min((right - left) / 2, (bottom - top) / 2),
    ),
  } satisfies SpotlightRect;
}

function buildRoundedRectPath(rect: SpotlightRect) {
  const radius = Math.min(rect.radius, rect.width / 2, rect.height / 2);

  return [
    `M ${rect.left + radius} ${rect.top}`,
    `H ${rect.right - radius}`,
    `A ${radius} ${radius} 0 0 1 ${rect.right} ${rect.top + radius}`,
    `V ${rect.bottom - radius}`,
    `A ${radius} ${radius} 0 0 1 ${rect.right - radius} ${rect.bottom}`,
    `H ${rect.left + radius}`,
    `A ${radius} ${radius} 0 0 1 ${rect.left} ${rect.bottom - radius}`,
    `V ${rect.top + radius}`,
    `A ${radius} ${radius} 0 0 1 ${rect.left + radius} ${rect.top}`,
    "Z",
  ].join(" ");
}

function getInteractiveMasks(rect: SpotlightRect) {
  return [
    {
      key: "top",
      style: {
        left: 0,
        top: 0,
        width: "100vw",
        height: rect.top,
      },
    },
    {
      key: "left",
      style: {
        left: 0,
        top: rect.top,
        width: rect.left,
        height: rect.height,
      },
    },
    {
      key: "right",
      style: {
        left: rect.right,
        top: rect.top,
        width: Math.max(window.innerWidth - rect.right, 0),
        height: rect.height,
      },
    },
    {
      key: "bottom",
      style: {
        left: 0,
        top: rect.bottom,
        width: "100vw",
        height: Math.max(window.innerHeight - rect.bottom, 0),
      },
    },
  ];
}

function getBubbleStyle(
  activeStepId: TutorialStepId,
  isLargeViewport: boolean,
): CSSProperties {
  if (!isLargeViewport || activeStepId === "welcome" || activeStepId === "finish") {
    return {
      left: "50%",
      top: "50%",
      transform: "translate(-50%, -50%)",
      width: `min(${CENTER_BUBBLE_WIDTH}px, calc(100vw - 32px))`,
    };
  }

  return {
    top: DESKTOP_BUBBLE_OFFSET,
    right: DESKTOP_BUBBLE_OFFSET,
    width: `min(${DESKTOP_BUBBLE_WIDTH}px, calc(100vw - 32px))`,
  };
}

type HomeTutorialOverlayProps = {
  appName: string;
  viewportMode: HomeViewportMode;
};

export function HomeTutorialOverlay({
  appName,
  viewportMode,
}: HomeTutorialOverlayProps) {
  const [currentStepId, setCurrentStepId] = useState<TutorialStepId>("welcome");
  const [isLargeViewport, setIsLargeViewport] = useState(false);
  const [spotlightRect, setSpotlightRect] = useState<SpotlightRect | null>(null);

  const activeStepId =
    currentStepId === "coach-switch" && viewportMode === "coach"
      ? "coach-workspace"
      : currentStepId;
  const currentStep = tutorialSteps[activeStepId];
  const isSimplifiedWelcome = !isLargeViewport;
  const canGoBack =
    !isSimplifiedWelcome &&
    activeStepId !== "welcome" &&
    activeStepId !== "scenarios";
  const showSpotlight =
    isLargeViewport &&
    activeStepId !== "welcome" &&
    activeStepId !== "finish" &&
    spotlightRect !== null;
  const bubbleStyle = useMemo(
    () => getBubbleStyle(activeStepId, isLargeViewport),
    [activeStepId, isLargeViewport],
  );
  const spotlightPath = useMemo(() => {
    if (!showSpotlight || spotlightRect === null || typeof window === "undefined") {
      return null;
    }

    const innerPath = buildRoundedRectPath(spotlightRect);
    return `M 0 0 H ${window.innerWidth} V ${window.innerHeight} H 0 Z ${innerPath}`;
  }, [showSpotlight, spotlightRect]);

  useEffect(() => {
    if (typeof window === "undefined") {
      return;
    }

    const mediaQuery = window.matchMedia(
      `(min-width: ${FULL_TUTORIAL_MIN_WIDTH}px)`,
    );
    const syncViewport = () => setIsLargeViewport(mediaQuery.matches);

    syncViewport();
    mediaQuery.addEventListener("change", syncViewport);

    return () => mediaQuery.removeEventListener("change", syncViewport);
  }, []);

  useEffect(() => {
    const previousOverflow = document.body.style.overflow;
    document.body.style.overflow = "hidden";

    return () => {
      document.body.style.overflow = previousOverflow;
    };
  }, []);

  useEffect(() => {
    if (
      !isLargeViewport ||
      currentStep.selectors === undefined ||
      activeStepId === "welcome" ||
      activeStepId === "finish"
    ) {
      return;
    }

    const updateRect = () => {
      setSpotlightRect(resolveSpotlightRect(currentStep.selectors ?? []));
    };

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

    return () => {
      window.removeEventListener("resize", updateRect);
      window.removeEventListener("scroll", updateRect, true);
    };
  }, [activeStepId, currentStep, isLargeViewport, viewportMode]);

  function closeTutorial() {
    completeDemoHomeTutorial();
  }

  function handlePrimaryAction() {
    if (isSimplifiedWelcome) {
      closeTutorial();
      return;
    }

    switch (activeStepId) {
      case "welcome":
        setCurrentStepId("scenarios");
        return;
      case "scenarios":
        setCurrentStepId("filters");
        return;
      case "filters":
        setCurrentStepId("sidebar");
        return;
      case "sidebar":
        setCurrentStepId("coach-switch");
        return;
      case "coach-workspace":
        setCurrentStepId("finish");
        return;
      case "finish":
        closeTutorial();
        return;
      default:
        return;
    }
  }

  function handleBackAction() {
    switch (activeStepId) {
      case "filters":
        setCurrentStepId("scenarios");
        return;
      case "sidebar":
        setCurrentStepId("filters");
        return;
      case "coach-switch":
        setCurrentStepId("sidebar");
        return;
      case "coach-workspace":
        setCurrentStepId("sidebar");
        return;
      case "finish":
        setCurrentStepId("coach-workspace");
        return;
      default:
        return;
    }
  }

  return (
    <div className="fixed inset-0 z-[80]" aria-hidden={false}>
      {showSpotlight && spotlightRect && spotlightPath ? (
        currentStep.waitingForCoachClick ? (
          <>
            <svg
              className="fixed inset-0 z-[80] h-full w-full"
              viewBox={`0 0 ${window.innerWidth} ${window.innerHeight}`}
              preserveAspectRatio="none"
              aria-hidden="true"
            >
              <path
                d={spotlightPath}
                fill="rgba(15,23,42,0.74)"
                fillRule="evenodd"
              />
            </svg>
            {getInteractiveMasks(spotlightRect).map((mask) => (
              <div
                key={mask.key}
                className="fixed z-[80] bg-transparent"
                style={mask.style}
              />
            ))}
          </>
        ) : (
          <>
            <svg
              className="fixed inset-0 z-[80] h-full w-full"
              viewBox={`0 0 ${window.innerWidth} ${window.innerHeight}`}
              preserveAspectRatio="none"
              aria-hidden="true"
            >
              <path
                d={spotlightPath}
                fill="rgba(15,23,42,0.74)"
                fillRule="evenodd"
              />
            </svg>
            <div
              className="fixed z-[81] bg-transparent"
              style={{
                left: spotlightRect.left,
                top: spotlightRect.top,
                width: spotlightRect.width,
                height: spotlightRect.height,
                borderRadius: spotlightRect.radius,
              }}
            />
          </>
        )
      ) : (
        <div className="fixed inset-0 bg-[rgba(15,23,42,0.78)]" />
      )}

      {showSpotlight && spotlightRect ? (
        <div
          className="tutorial-ring pointer-events-none fixed z-[82]"
          style={{
            left: spotlightRect.left,
            top: spotlightRect.top,
            width: spotlightRect.width,
            height: spotlightRect.height,
            borderRadius: spotlightRect.radius,
          }}
        />
      ) : null}

      <section
        role="dialog"
        aria-modal="true"
        aria-label="Guide de prise en main"
        className="fixed z-[83] rounded-[24px] border border-white/12 bg-[rgba(255,255,255,0.97)] p-5 text-[var(--foreground)] shadow-[0_30px_80px_rgba(15,23,42,0.34)]"
        style={bubbleStyle}
      >
        <h2 className="text-xl font-bold leading-tight text-[var(--ink)]">
          {activeStepId === "welcome" ? `Bienvenue sur ${appName}` : currentStep.title}
        </h2>

        <p className="mt-3 text-[13px] leading-6 text-[var(--foreground)]">
          {currentStep.description}
        </p>

        <div className="mt-5 flex flex-wrap items-center justify-between gap-2">
          <div className="flex flex-wrap gap-2">
            {canGoBack ? (
              <button
                type="button"
                onClick={handleBackAction}
                className="inline-flex items-center justify-center rounded-full border border-[var(--line)] bg-white px-4 py-2.5 text-sm font-semibold text-[var(--foreground)] transition-colors hover:border-[var(--primary)] hover:text-[var(--primary)]"
              >
                {currentStep.backLabel ?? "Retour"}
              </button>
            ) : null}
            <button
              type="button"
              onClick={closeTutorial}
              className="inline-flex items-center justify-center rounded-full border border-[var(--line)] bg-white px-4 py-2.5 text-sm font-semibold text-[var(--foreground)] transition-colors hover:border-[var(--accent-red)] hover:text-[var(--accent-red)]"
            >
              Passer
            </button>
          </div>

          {!currentStep.waitingForCoachClick ? (
            <button
              type="button"
              onClick={handlePrimaryAction}
              className="inline-flex items-center justify-center rounded-full bg-[linear-gradient(135deg,var(--primary)_0%,#3e97d6_100%)] px-5 py-2.5 text-sm font-semibold text-white shadow-[0_14px_30px_rgba(23,117,186,0.24)] transition-transform duration-200 hover:-translate-y-0.5"
            >
              {currentStep.primaryLabel ?? "Suivant"}
            </button>
          ) : null}
        </div>
      </section>
    </div>
  );
}
