"use client";

import { useEffect, useRef, useState, type FormEvent } from "react";
import Image from "next/image";
import Link from "next/link";
import { AnimatePresence, motion } from "motion/react";

const features = [
  {
    icon: "/icon-sparkle-wrapper.svg",
    title: "7 Tage. Ein Fokus.",
    desc: "Tägliche Impulse für mehr Klarheit und weniger Reibung.",
  },
  {
    icon: "/icon-checklist.png",
    title: "Praktisch & umsetzbar.",
    desc: "Direkt anwendbare Methoden für deinen Alltag.",
  },
  {
    icon: "/icon-heart.png",
    title: "Kein Spam. Versprochen.",
    desc: "Nur wertvolle Inhalte, wenn du sie brauchst.",
  },
];

/**
 * The Navbar's "Newsletter" CTA opens this modal rather than navigating —
 * matches the original Figma prototype (Newsletter-Button → Overlay
 * newsletter-overlay), unlike the Werkzeuge "Impulse & Tipps" card's
 * "Anmelden" link, which goes to the full /newsletter detail page instead.
 * Different entry points, different weight: a quick-access nav CTA gets a
 * lightweight in-place signup, a content card gets the full page.
 */
export function NewsletterModal({ open, onClose }: { open: boolean; onClose: () => void }) {
  const dialogRef = useRef<HTMLDivElement>(null);
  const closeButtonRef = useRef<HTMLButtonElement>(null);
  const [email, setEmail] = useState("");
  const [consent, setConsent] = useState(false);
  const [status, setStatus] = useState<"idle" | "submitting" | "success" | "error">("idle");
  const [error, setError] = useState("");

  async function handleSubmit(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    setStatus("submitting");
    setError("");
    try {
      const res = await fetch("/api/newsletter/subscribe", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email, consent, source: "newsletter-modal" }),
      });
      const data = await res.json();
      if (!data.ok) {
        setError(data.reason || "Anmeldung ist fehlgeschlagen. Bitte versuche es später erneut.");
        setStatus("error");
        return;
      }
      setStatus("success");
    } catch {
      setError("Anmeldung ist fehlgeschlagen. Bitte versuche es später erneut.");
      setStatus("error");
    }
  }

  // Background scroll lock while open — intercepts and cancels the wheel/
  // touch input that would cause scrolling, instead of toggling
  // overflow/position on body or html. Two earlier approaches (plain
  // overflow:hidden on body; position:fixed with a negative top offset to
  // compensate) each fixed one symptom while causing another — overflow
  // alone reset scrollY to 0 for a frame when opened away from the top of
  // the page (e.g. parked at #ueber-bjoern), and position:fixed took body
  // out of normal flow, which detached the Navbar's `position: sticky`
  // from its scrolling container and made it visibly snap. Neither is a
  // risk here: scrollY, overflow and layout are never touched at all, so
  // there's nothing that can jump, reflow, or need restoring on close —
  // the events that would move the page just never get to.
  // `{ passive: false }` is required for preventDefault() to have any
  // effect on wheel/touchmove. Events that originate inside the dialog
  // (which has its own overflow-y-auto) are let through untouched, so the
  // modal's own content still scrolls normally.
  useEffect(() => {
    if (!open) return;

    const isInsideDialog = (target: EventTarget | null) =>
      target instanceof Node && !!dialogRef.current?.contains(target);

    const onWheel = (e: WheelEvent) => {
      if (!isInsideDialog(e.target)) e.preventDefault();
    };
    const onTouchMove = (e: TouchEvent) => {
      if (!isInsideDialog(e.target)) e.preventDefault();
    };

    document.addEventListener("wheel", onWheel, { passive: false });
    document.addEventListener("touchmove", onTouchMove, { passive: false });
    return () => {
      document.removeEventListener("wheel", onWheel);
      document.removeEventListener("touchmove", onTouchMove);
    };
  }, [open]);

  // Focus management: move focus into the modal on open, trap Tab within
  // it, close + return focus on Escape — same pattern as the Navbar's
  // mobile drawer.
  useEffect(() => {
    if (!open) return;

    // preventScroll: true — otherwise the browser's implicit
    // scrollIntoView on focus() sees this button sitting close to the
    // viewport's top edge and "corrects" for the global
    // scroll-padding-top (reserved for the sticky Navbar, see
    // globals.css) by nudging the whole page upward — pointless here
    // since the modal is position:fixed and always fully in view
    // regardless of document scroll, but that nudge is exactly the
    // "page scrolls up a bit and the modal lands in a weird position"
    // jank on open.
    closeButtonRef.current?.focus({ preventScroll: true });

    const onKeyDown = (e: KeyboardEvent) => {
      if (e.key === "Escape") {
        e.preventDefault();
        onClose();
        return;
      }
      if (e.key !== "Tab") return;
      const focusables = dialogRef.current?.querySelectorAll<HTMLElement>(
        'a[href], button:not([disabled]), input:not([disabled])'
      );
      if (!focusables || focusables.length === 0) return;
      const first = focusables[0];
      const last = focusables[focusables.length - 1];
      if (e.shiftKey && document.activeElement === first) {
        e.preventDefault();
        last.focus({ preventScroll: true });
      } else if (!e.shiftKey && document.activeElement === last) {
        e.preventDefault();
        first.focus({ preventScroll: true });
      }
    };

    document.addEventListener("keydown", onKeyDown);
    return () => document.removeEventListener("keydown", onKeyDown);
  }, [open, onClose]);

  return (
    // AnimatePresence, not a plain `if (!open) return null` — that would
    // unmount the modal instantly on close with no way to play an exit
    // animation first. Keeping it mounted (conditionally rendering the
    // child) lets Framer Motion finish the fade-out before removing it.
    <AnimatePresence>
      {open && (
        <motion.div
          className="fixed inset-0 z-[60] flex items-center justify-center p-4 md:p-8 bg-[rgba(134,134,134,0.9)]"
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          transition={{ duration: 0.25, ease: "easeOut" }}
          onClick={(e) => {
            if (e.target === e.currentTarget) onClose();
          }}
        >
          <motion.div
            ref={dialogRef}
            role="dialog"
            aria-modal="true"
            aria-labelledby="newsletter-modal-heading"
            initial={{ opacity: 0, y: 16, scale: 0.97 }}
            animate={{ opacity: 1, y: 0, scale: 1 }}
            exit={{ opacity: 0, y: 16, scale: 0.97 }}
            transition={{ duration: 0.3, ease: [0.22, 1, 0.36, 1] }}
            className="relative bg-bg-base rounded-md overflow-hidden w-full max-w-[75rem] max-h-[90vh] overflow-y-auto"
          >
        <button
          ref={closeButtonRef}
          type="button"
          onClick={onClose}
          aria-label="Schließen"
          className="absolute top-6 right-6 z-10 size-6 flex items-center justify-center active:scale-90 transition-transform"
        >
          <Image alt="" src="/icon-close.png" width={24} height={24} className="size-full object-contain" />
        </button>

        {/* modal-top: photo + copy/form, stacked below md */}
        <div className="flex flex-col md:flex-row items-stretch border-b border-border">
          <div className="relative w-full md:flex-1 aspect-[4/3] md:aspect-auto">
            <Image
              src="/newsletter-modal-photo.jpg"
              alt="Notizbuch mit Kaffee und Stift"
              fill
              sizes="(min-width: 768px) 50vw, 100vw"
              className="object-cover"
            />
          </div>

          <div className="flex flex-col gap-6 items-start justify-center flex-1 min-w-0 px-8 py-10 md:px-[4.6875rem] md:py-[6.25rem]">
            {/* -scale-y-100 is required, not just -rotate-4 — the SVG
                itself is authored upside-down (matches how Newsletter.tsx
                uses this exact same asset); without it the icon renders
                flipped. */}
            <div className="w-16 h-14 -rotate-4 -scale-y-100">
              <Image alt="" src="/newsletter-icon.svg" width={64} height={56} className="w-full h-full" />
            </div>

            <p
              id="newsletter-modal-heading"
              className="font-semibold text-h-feature text-text-primary leading-[1.15]"
              style={{ fontFamily: "var(--font-lora)" }}
            >
              Starte mit einer Woche voller Klarheit<span className="text-brand">.</span>
            </p>

            <p className="text-body text-text-primary">
              Melde dich zum Newsletter an und erhalte die 7-Tage-Challenge, mit der du durch mehr Struktur weniger Stress spürst.
            </p>

            {status === "success" ? (
              <p className="text-body text-text-primary font-medium">
                Danke! Du bist jetzt für den Newsletter angemeldet.
              </p>
            ) : (
              <form onSubmit={handleSubmit} className="flex flex-col gap-5 items-start w-full">
                <div className="flex flex-col gap-4 items-start w-full">
                  <input
                    type="email"
                    required
                    value={email}
                    onChange={(e) => setEmail(e.target.value)}
                    placeholder="Deine E-Mail-Adresse"
                    className="w-full bg-bg-white border border-border rounded-sm px-6 py-3 text-body text-text-muted font-normal outline-none focus:border-brand transition-colors"
                  />
                  <button
                    type="submit"
                    disabled={status === "submitting"}
                    className="w-full bg-brand rounded-sm px-7 py-[0.875rem] font-bold text-h4 text-text-primary text-left hover:bg-brand-hover active:scale-[0.97] transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2 focus-visible:ring-offset-bg-base disabled:opacity-60 disabled:pointer-events-none"
                  >
                    {status === "submitting" ? "Wird gesendet…" : "Jetzt anmelden"}
                  </button>
                </div>
                <label className="flex gap-2 items-center w-full cursor-pointer">
                  <input
                    type="checkbox"
                    required
                    checked={consent}
                    onChange={(e) => setConsent(e.target.checked)}
                    className="size-4 shrink-0 rounded-xs border border-border accent-brand"
                  />
                  <span className="text-label text-text-primary">
                    Ich akzeptiere die{" "}
                    <Link
                      href="/datenschutz"
                      target="_blank"
                      rel="noopener noreferrer"
                      className="underline hover:text-brand"
                    >
                      Datenschutzerklärung
                    </Link>
                    .
                  </span>
                </label>
                {status === "error" && (
                  <p className="text-label text-red-600 font-normal">{error}</p>
                )}
              </form>
            )}
          </div>
        </div>

        {/* modal-bottom: 3 feature cards. Figma's export had items-end on
            this row, but that's a byproduct of nested -scale-y-100
            flip-wrappers Figma uses for baseline-grid tricks (visually
            cancels out to top-alignment in the actual design) — taken
            literally it bottom-aligned the icon with the last line of
            description text instead of the title, which read as broken.
            items-start + a fixed icon bounding box (icons have different
            native proportions, e.g. the sparkle glyph isn't square) fixes
            it without needing the flip trick. */}
        <div className="flex flex-col md:flex-row items-start px-8 md:px-20 py-6 md:py-9 gap-8 md:gap-6">
          {features.map((f) => (
            <div key={f.title} className="flex-1 flex gap-6 items-start w-full">
              <div className="relative h-10 w-10 shrink-0 flex items-center justify-center">
                <Image alt="" src={f.icon} fill sizes="40px" className="object-contain" />
              </div>
              <div className="flex flex-col gap-3 items-start flex-1 min-w-0">
                <p
                  className="font-semibold text-h-small text-text-primary w-full"
                  style={{ fontFamily: "var(--font-lora)" }}
                >
                  {f.title}
                </p>
                <p className="text-body text-text-primary w-full">{f.desc}</p>
              </div>
            </div>
          ))}
          </div>
          </motion.div>
        </motion.div>
      )}
    </AnimatePresence>
  );
}
