"use client";

// components/landing/BottomCta.tsx
// Floating "Quiero participar" CTA (§4). A side-anchored (bottom-right) button
// that keeps the call to action one thumb-reach away on a long landing and
// smooth-scrolls to the donation form (#donar) via Lenis. It replaces the older
// full-width bottom bar so the first thing a user can do is open the form.
//
// It portals into the layout's #persistent-cta-slot (a fixed, pointer-events-none
// region owned by app/(public)/layout.tsx). Only the button surface re-enables
// pointer events, so the rest of the slot never blocks taps.
//
// Accessibility:
//   - The bar is a <nav> landmark labeled in Spanish, keyboard reachable in DOM
//     order, links are real anchors with 44px tap targets, visible focus ring.
//   - prefers-reduced-motion: the slide-in/fade is disabled (the bar appears
//     immediately), honoring the motion gate. No information is motion-only.
//   - The bar is hidden from the layout flow but does NOT trap focus.

import * as React from "react";
import { createPortal } from "react-dom";
import Link from "next/link";

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;
}

export function BottomCta() {
  const reduced = usePrefersReducedMotion();
  const [slot, setSlot] = React.useState<HTMLElement | null>(null);
  const [visible, setVisible] = React.useState(false);

  // Resolve the portal target and trigger the reveal inside a rAF callback. All
  // setState happens in the asynchronous rAF callback (never synchronously in
  // the effect body) so the slide-in transition runs from the off-screen start
  // state and the no-synchronous-setState-in-effect rule is satisfied. On the
  // server and the first client render `slot` is null, so nothing renders until
  // mount, keeping SSR and hydration consistent.
  React.useEffect(() => {
    const node = document.getElementById("persistent-cta-slot");
    if (!node) return;
    let inner = 0;
    // Frame 1: mount the bar in its hidden start state. Frame 2: flip visible so
    // the transition animates. Both setState calls run in async rAF callbacks.
    const outer = window.requestAnimationFrame(() => {
      setSlot(node);
      inner = window.requestAnimationFrame(() => setVisible(true));
    });
    return () => {
      window.cancelAnimationFrame(outer);
      window.cancelAnimationFrame(inner);
    };
  }, []);

  if (!slot) return null;

  const transformStyle: React.CSSProperties = reduced
    ? { transform: "none", opacity: 1, transition: "none" }
    : {
        transform: visible ? "translateY(0)" : "translateY(100%)",
        opacity: visible ? 1 : 0,
        transition: "transform 0.3s var(--ease-standard), opacity 0.3s ease",
      };

  return createPortal(
    <div className="pointer-events-none flex justify-end px-4 pb-4 sm:px-6 sm:pb-6">
      <nav
        aria-label="Acción principal"
        className="pointer-events-auto"
        style={transformStyle}
      >
        <Link
          href="/#donar"
          className="inline-flex min-h-[52px] items-center justify-center rounded-full bg-primary px-7 py-3 font-body text-button font-bold text-on-primary shadow-drop hover:bg-primary-soft focus-visible:outline focus-visible:outline-[3px] focus-visible:outline-offset-2 focus-visible:outline-steelblue"
        >
          Quiero participar
        </Link>
      </nav>
    </div>,
    slot,
  );
}
