"use client";

// components/landing/Faq.tsx
// FAQ that doubles as trust content (ux.md 1.9, 6). Still built on native
// <details>/<summary>: keyboard operable, screen-reader-friendly disclosure
// semantics, and a working no-JS / pre-hydration fallback (clicking a summary
// toggles natively before this component hydrates). The "Como se eligen los
// ganadores" and "A donde va mi dinero" answers are written straight (no jokes),
// and the refunds + age-requirement answers are explicit.
//
// Enhancement (layered on top, never required): once hydrated, each item
// intercepts the toggle and animates the answer's height + opacity open/close
// with GSAP, and rotates the +/x indicator in sync.
//
// Accessibility:
//   - prefers-reduced-motion: the open/close still works but with duration 0
//     (instant), so no animation plays. The icon transition is also disabled.
//   - The native <details> open state is what assistive tech announces; the
//     indicator and the animation are decorative.
//
// basesUrl, when present, is linked inline so the official bases are reachable
// from the trust content too.

import * as React from "react";
import { gsap } from "gsap";
import { AnimatedHeading } from "./AnimatedHeading";

export interface FaqProps {
  basesUrl: string | null;
}

interface QA {
  q: string;
  a: React.ReactNode;
}

function usePrefersReducedMotion(): boolean {
  const [reduced, setReduced] = React.useState(false);
  React.useEffect(() => {
    if (typeof window === "undefined" || !window.matchMedia) return;
    const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
    const update = () => setReduced(mq.matches);
    update();
    mq.addEventListener?.("change", update);
    return () => mq.removeEventListener?.("change", update);
  }, []);
  return reduced;
}

function buildItems(basesUrl: string | null): QA[] {
  const basesLink = basesUrl ? (
    <>
      {" "}
      Puedes leer las bases del sorteo{" "}
      <a
        href={basesUrl}
        target="_blank"
        rel="noopener noreferrer"
        className="font-bold text-steelblue underline"
      >
        aquí (abre en una pestaña nueva)
      </a>
      .
    </>
  ) : null;

  return [
    {
      q: "¿Cómo se eligen los ganadores?",
      a: (
        <>
          El sorteo se realiza de forma transparente y supervisada. Los ganadores
          se eligen con un método documentado y reproducible, a partir de una
          lista congelada de los boletos confirmados al cierre. Cualquier persona
          puede verificar el resultado después del sorteo.{basesLink}
        </>
      ),
    },
    {
      q: "¿A dónde va mi dinero?",
      a: (
        <>
          Tu aporte va a Teletón para que más chicos reciban atención, terapia y
          rehabilitación. Cada sol recibido se administra de forma responsable y
          se rinde cuenta de forma pública.
        </>
      ),
    },
    {
      q: "¿Puedo pedir la devolución de mi pago?",
      a: (
        <>
          Si tu pago no se completa, tu inscripción no queda confirmada y no se te
          cobra. Las solicitudes de devolución de pagos ya confirmados se atienden
          según las bases del sorteo y la normativa vigente. Escríbenos y te
          ayudamos.{basesLink}
        </>
      ),
    },
    {
      q: "¿Quién puede participar?",
      a: (
        <>
          Pueden participar personas mayores de edad. Al inscribirte confirmas que
          eres mayor de edad y que aceptas las bases del sorteo.
        </>
      ),
    },
    {
      q: "¿Mi pago es seguro?",
      a: (
        <>
          Sí. El pago se procesa por una plataforma de pago segura. Recibes la
          confirmación en tu correo apenas se confirma tu aporte.
        </>
      ),
    },
    {
      q: "¿Cuántas chances me dan?",
      a: (
        <>
          Empiezas con una chance y puedes sumar más si quieres. Mientras más
          chances tienes, más posibilidades de ganar. Nunca está garantizado, pero
          siempre suma a la causa.
        </>
      ),
    },
  ];
}

function FaqItem({ item, reduced }: { item: QA; reduced: boolean }) {
  const detailsRef = React.useRef<HTMLDetailsElement>(null);
  const contentRef = React.useRef<HTMLDivElement>(null);
  const tweenRef = React.useRef<gsap.core.Tween | null>(null);
  // Drives ONLY the indicator rotation. The disclosure state of record is the
  // native <details open> attribute, set imperatively below.
  const [open, setOpen] = React.useState(false);

  // Clean up any in-flight tween if the item unmounts mid-animation.
  React.useEffect(
    () => () => {
      tweenRef.current?.kill();
    },
    [],
  );

  const handleToggle = (event: React.MouseEvent<HTMLElement>) => {
    const details = detailsRef.current;
    const content = contentRef.current;
    if (!details || !content) return;

    // We own the toggle so the close can animate before the content is removed.
    // preventDefault cancels the native toggle for BOTH mouse and keyboard
    // (Enter/Space on a summary dispatches a click), so our path always runs.
    event.preventDefault();
    tweenRef.current?.kill();

    // Branch on the React `open` state, NOT details.open. On close, details.open
    // is only flipped to false in the tween's onComplete (~0.32s later, kept for
    // the accessibility announcement), so reading it here would invert a rapid
    // re-click during the close (a double-tap would re-close instead of reopen).
    // `open` is committed synchronously between clicks, so it reflects intent.
    const opening = !open;
    const duration = reduced ? 0 : opening ? 0.4 : 0.32;

    if (opening) {
      details.open = true; // content must be in-flow to measure its height
      setOpen(true);
      gsap.set(content, { height: "auto", overflow: "hidden" });
      tweenRef.current = gsap.from(content, {
        height: 0,
        opacity: 0,
        duration,
        ease: "power2.out",
        onComplete: () => {
          // Restore natural flow so a resize / font swap can't clip the answer.
          gsap.set(content, { clearProps: "height,overflow,opacity" });
        },
      });
    } else {
      setOpen(false);
      gsap.set(content, { overflow: "hidden" });
      tweenRef.current = gsap.to(content, {
        height: 0,
        opacity: 0,
        duration,
        ease: "power2.in",
        onComplete: () => {
          details.open = false; // now the UA hides it; safe to drop inline state
          gsap.set(content, { clearProps: "height,overflow,opacity" });
        },
      });
    }
  };

  return (
    <details
      ref={detailsRef}
      className="group rounded-lg border border-hairline bg-canvas"
    >
      <summary
        onClick={handleToggle}
        className="flex min-h-[44px] cursor-pointer list-none items-center justify-between gap-md px-md py-3 font-body text-heading-sm font-bold text-ink-strong focus-visible:outline focus-visible:outline-[3px] focus-visible:outline-offset-2 focus-visible:outline-steelblue"
      >
        <span>{item.q}</span>
        {/* Decorative open/close indicator. Rotation is driven by `open` state
            (synced to the user's action), not the native attribute, so it
            animates back the instant a close begins. The transition is disabled
            under reduced motion. */}
        <span
          aria-hidden="true"
          className={`text-primary ${open ? "rotate-45" : ""}`}
          style={{
            transition: reduced
              ? "none"
              : "transform 0.3s var(--ease-standard)",
          }}
        >
          +
        </span>
      </summary>
      <div
        ref={contentRef}
        className="px-md pb-md font-body text-body-md text-muted"
      >
        {item.a}
      </div>
    </details>
  );
}

export function Faq({ basesUrl }: FaqProps) {
  const items = buildItems(basesUrl);
  const reduced = usePrefersReducedMotion();
  return (
    <section className="bg-canvas px-5 py-section" aria-labelledby="faq-title">
      <div className="mx-auto max-w-[760px]">
        <AnimatedHeading
          as="h2"
          id="faq-title"
          className="text-center font-display text-heading-lg font-bold text-ink-strong"
        >
          Preguntas frecuentes
        </AnimatedHeading>
        <div className="mt-lg flex flex-col gap-3">
          {items.map((item) => (
            <FaqItem key={item.q} item={item} reduced={reduced} />
          ))}
        </div>
      </div>
    </section>
  );
}
