// Brigzy redesign — interactive bits
const { useState, useEffect, useRef } = React;

// Skip hover-only effects (cursor spotlight, magnetic buttons, 3D tilt) on touch devices —
// they require a hover-capable pointer to make sense.
const IS_TOUCH = typeof window !== "undefined"
  && window.matchMedia
  && window.matchMedia("(hover: none) and (pointer: coarse)").matches;

/* ---------- API ENDPOINTS ---------- */
const SUPABASE_FN_BASE = "https://dygjwtljgzfyoqdklcrk.supabase.co/functions/v1";
const WAITLIST_SIGNUP_URL = `${SUPABASE_FN_BASE}/waitlist-signup`;
const LANDING_STATS_URL = `${SUPABASE_FN_BASE}/landing-stats`;

/* ---------- TWEAKS ---------- */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#7c3aed"
}/*EDITMODE-END*/;

const ACCENT_OPTIONS = [
  "#7c3aed", // Brigzy purple (default)
  "#a78bfa", // light lavender
  "#e8704a", // terracotta
  "#14110d", // ink (monochrome)
];

function applyTweaks(t) {
  document.documentElement.style.setProperty("--accent", t.accent);
  const hex = t.accent.replace("#", "");
  const r = parseInt(hex.slice(0,2), 16);
  const g = parseInt(hex.slice(2,4), 16);
  const b = parseInt(hex.slice(4,6), 16);
  document.documentElement.style.setProperty("--accent-soft", `rgba(${r}, ${g}, ${b}, 0.08)`);
}

/* ---------- THEME TOGGLE ----------
   Initial class is set by the inline bootstrap script in <head>.
   This wires the button click + listens for system preference changes
   (only when the user has not set an explicit override). */
function setupThemeToggle() {
  const THEME_KEY = "brigzy-theme";
  const btn = document.getElementById("themeToggle");
  if (!btn) return;

  btn.addEventListener("click", () => {
    const nowDark = !document.documentElement.classList.contains("dark");
    document.documentElement.classList.toggle("dark", nowDark);
    try { localStorage.setItem(THEME_KEY, nowDark ? "dark" : "light"); } catch (_) {}
  });

  // Follow system preference for users who haven't overridden.
  if (window.matchMedia) {
    const mq = window.matchMedia("(prefers-color-scheme: dark)");
    const onChange = (e) => {
      let hasOverride = false;
      try { hasOverride = !!localStorage.getItem(THEME_KEY); } catch (_) {}
      if (!hasOverride) document.documentElement.classList.toggle("dark", e.matches);
    };
    if (mq.addEventListener) mq.addEventListener("change", onChange);
    else if (mq.addListener) mq.addListener(onChange); // Safari < 14 fallback
  }
}

/* ---------- LIVE WAITLIST COUNTER ---------- */
// Fetches real waitlist count from Supabase landing-stats edge function.
// Refreshes every 30s (matches function's Cache-Control). Flashes on increment.
function LiveWaitlistCounter({ initialCount = null }) {
  const [count, setCount] = useState(initialCount);
  const [flash, setFlash] = useState(false);
  const prevRef = useRef(initialCount);

  useEffect(() => {
    let mounted = true;
    const fetchCount = async () => {
      try {
        const res = await fetch(LANDING_STATS_URL);
        if (!res.ok) return;
        const data = await res.json();
        if (!mounted || typeof data.waitlist !== "number") return;
        if (prevRef.current !== null && data.waitlist > prevRef.current) {
          setFlash(true);
          setTimeout(() => { if (mounted) setFlash(false); }, 600);
        }
        prevRef.current = data.waitlist;
        setCount(data.waitlist);
      } catch (_) { /* silent fail — keep last known value */ }
    };
    fetchCount();
    const id = setInterval(fetchCount, 30000);
    return () => { mounted = false; clearInterval(id); };
  }, []);

  if (count === null) {
    return <span className="counter-num" style={{ opacity: 0.5 }}>···</span>;
  }
  return <span className={`counter-num ${flash ? "flash" : ""}`}>{count.toLocaleString("sk-SK")}</span>;
}

/* ---------- WAITLIST FORM ---------- */
function WaitlistForm({ variant }) {
  const [email, setEmail] = useState("");
  const [website, setWebsite] = useState(""); // honeypot — bots fill, humans don't
  const [state, setState] = useState("idle"); // idle | loading | done
  const [errorMsg, setErrorMsg] = useState("");
  const [signupPosition, setSignupPosition] = useState(null);
  const btnRef = useRef(null);

  // Magnetic effect
  useEffect(() => {
    if (IS_TOUCH) return;
    const btn = btnRef.current;
    if (!btn) return;
    const onMove = (e) => {
      const r = btn.getBoundingClientRect();
      const x = e.clientX - (r.left + r.width / 2);
      const y = e.clientY - (r.top + r.height / 2);
      const dist = Math.hypot(x, y);
      if (dist < 80) {
        btn.style.transform = `translate(${x * 0.25}px, ${y * 0.25}px)`;
      } else {
        btn.style.transform = "";
      }
    };
    const onLeave = () => { btn.style.transform = ""; };
    window.addEventListener("mousemove", onMove);
    btn.addEventListener("mouseleave", onLeave);
    return () => {
      window.removeEventListener("mousemove", onMove);
      btn.removeEventListener("mouseleave", onLeave);
    };
  }, []);

  const handle = async (e) => {
    e.preventDefault();
    if (!email.includes("@") || state === "loading") return;
    setState("loading");
    setErrorMsg("");

    try {
      const res = await fetch(WAITLIST_SIGNUP_URL, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ email: email.trim(), website }),
      });
      const data = await res.json().catch(() => ({}));

      if (res.ok && data.ok) {
        if (typeof data.count === "number") setSignupPosition(data.count);
        setState("done");
        return;
      }

      // Map known error codes
      if (data.error === "invalid_email") {
        setErrorMsg("Tento email nemôžeme prijať. Skontroluj ho prosím.");
      } else {
        setErrorMsg("Niečo sa pokazilo. Skús to ešte raz o chvíľu.");
      }
      setState("idle");
    } catch (err) {
      setErrorMsg("Pripojenie zlyhalo. Skontroluj internet a skús znova.");
      setState("idle");
    }
  };

  if (state === "done") {
    return (
      <div className="waitlist">
        <div style={{ width: "100%", maxWidth: 440 }}>
          <div className="waitlist-form" style={{ justifyContent: "center" }}>
            <div className="waitlist-success">
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                <polyline points="20 6 9 17 4 12"/>
              </svg>
              Si na zozname. Ozveme sa hneď, ako spustíme.
            </div>
          </div>
          <div className="waitlist-meta" style={{ textAlign: "center" }}>
            <span className="waitlist-avatars">
              <span className="waitlist-avatar"></span>
              <span className="waitlist-avatar"></span>
              <span className="waitlist-avatar"></span>
              <span className="waitlist-avatar"></span>
            </span>
            {signupPosition
              ? <>MIESTO #{signupPosition.toLocaleString("sk-SK")} · ĎAKUJEME</>
              : <>ĎAKUJEME · BUDEŠ MEDZI PRVÝMI</>
            }
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="waitlist">
      <div style={{ width: "100%", maxWidth: 440 }}>
        <form className="waitlist-form" onSubmit={handle} noValidate>
          <input
            className="waitlist-input"
            type="email"
            placeholder="tvoj@email.sk"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            disabled={state === "loading"}
            required
          />
          {/* Honeypot — hidden from real users, traps bots */}
          <input
            type="text"
            name="website"
            value={website}
            onChange={(e) => setWebsite(e.target.value)}
            tabIndex={-1}
            autoComplete="off"
            aria-hidden="true"
            style={{ position: "absolute", left: "-9999px", top: 0, opacity: 0, pointerEvents: "none", height: 0, width: 0 }}
          />
          <button ref={btnRef} className="waitlist-btn" type="submit" disabled={state === "loading"}>
            {state === "loading" ? "..." : "Pridať sa"}
            {state !== "loading" && (
              <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                <line x1="5" y1="12" x2="19" y2="12"/>
                <polyline points="12 5 19 12 12 19"/>
              </svg>
            )}
          </button>
        </form>
        {errorMsg && (
          <div className="waitlist-error" role="alert">
            {errorMsg}
          </div>
        )}
        <div className="waitlist-meta" style={{ textAlign: "center" }}>
          <span className="waitlist-avatars">
            <span className="waitlist-avatar"></span>
            <span className="waitlist-avatar"></span>
            <span className="waitlist-avatar"></span>
            <span className="waitlist-avatar"></span>
          </span>
          <LiveWaitlistCounter /> ĽUDÍ UŽ ČAKÁ · BEZ SPAMU
        </div>
      </div>
    </div>
  );
}

/* ---------- FAQ ---------- */
const FAQ_ITEMS = [
  { q: "Je Brigzy zadarmo?", a: "Áno. Stiahnutie a používanie appky je zadarmo pre pracovníkov aj firmy. Pri úspešnom dohodnutí brigády si Brigzy berie malú províziu, ktorá pokrýva platobnú bránu a podporu — žiadne mesačné poplatky, žiadne skryté čísla." },
  { q: "Kedy bude appka dostupná?", a: "Spúšťame už čoskoro — v App Store aj Google Play. Ľudia z waitlistu dostanú prístup ako prví, približne 2-3 týždne pred verejným launchom." },
  { q: "Ako fungujú platby?", a: "Brigzy používa escrow systém. Firma vloží platbu pred začiatkom práce a tá sa pracovníkovi uvoľní až po dokončení. Ak je niečo zle, máme tu support, ktorý spor vyrieši." },
  { q: "Pre koho je Brigzy určené?", a: "Pre študentov hľadajúcich brigádu, ľudí na materskej, profesionálov s voľnými dňami — aj pre firmy, kaviarne, sklady alebo eventy, ktoré potrebujú rýchlu výpomoc bez agentúrnych marží." },
  { q: "Ako je to s mojím súkromím?", a: "Tvoje dáta sú šifrované a chránené podľa GDPR. Nikdy ich neposúvame tretím stranám bez tvojho súhlasu. Viac v Ochrane súkromia." },
  { q: "Môžem zrušiť účet a zmazať dáta?", a: "Kedykoľvek. V nastaveniach máš jedno tlačidlo, ktoré všetko zruší a vymaže — bez emailov, bez prosenia, bez týždňového čakania." },
];

function FAQ() {
  const [open, setOpen] = useState(0);
  return (
    <div>
      {FAQ_ITEMS.map((item, i) => (
        <div key={i} className={`faq-item ${open === i ? "open" : ""}`}>
          <button className="faq-q" onClick={() => setOpen(open === i ? -1 : i)} aria-expanded={open === i}>
            <span>{item.q}</span>
            <span className="faq-icon"></span>
          </button>
          <div className="faq-a"><div className="faq-a-inner">{item.a}</div></div>
        </div>
      ))}
    </div>
  );
}

/* ---------- MARQUEE ---------- */
const CATEGORIES = ["Gastro", "Sklady", "Kaviarne", "Eventy", "Doučovanie", "Doručovanie", "IT brigády", "Stavebníctvo", "Maloobchod", "Letné tábory", "Festivaly", "Marketing", "Stánky"];
function Marquee() {
  const items = [...CATEGORIES, ...CATEGORIES];
  return <>{items.map((c, i) => <span key={i} className="marquee-item">{c}</span>)}</>;
}

/* ---------- PHONE CARD CYCLER ---------- */
const JOBS = [
  { co: "Bistro Vesna", title: "Barista — víkend", dist: "0.4 km", hours: "8h", pay: "€11", tag: "urgent", tagText: "Dnes" },
  { co: "Hala Logistika SK", title: "Triedenie balíkov", dist: "2.1 km", hours: "6h", pay: "€9", tag: "new", tagText: "Nové" },
  { co: "Festival Pohoda", title: "Hostess / Stánok", dist: "3.7 km", hours: "10h", pay: "€13", tag: "urgent", tagText: "Hneď" },
  { co: "Mestská knižnica", title: "Doučovanie ZŠ", dist: "1.2 km", hours: "4h", pay: "€10", tag: "new", tagText: "Nové" },
  { co: "Café Štúrova", title: "Čašník — večery", dist: "0.8 km", hours: "5h", pay: "€12", tag: "urgent", tagText: "Dnes" },
];

function PhoneCardCycler() {
  const [idx, setIdx] = useState(0);
  useEffect(() => {
    const id = setInterval(() => setIdx(i => (i + 1) % JOBS.length), 2800);
    return () => clearInterval(id);
  }, []);
  // show two cards: current and next
  const a = JOBS[idx];
  const b = JOBS[(idx + 1) % JOBS.length];
  const Card = ({ job, k }) => (
    <div className="phone-card enter" key={k}>
      <div className="phone-card-row">
        <div>
          <div className="phone-card-co">{job.co}</div>
          <div className="phone-card-title">{job.title}</div>
        </div>
        <span className={`phone-tag ${job.tag}`}>{job.tagText}</span>
      </div>
      <div className="phone-card-meta">
        <span>↗ {job.dist}</span>
        <span>○ {job.hours}</span>
      </div>
      <div className="phone-card-bottom">
        <div className="phone-card-pay">{job.pay}<sup>/h</sup></div>
        <span className="phone-apply">Uchádzať sa</span>
      </div>
    </div>
  );
  return (
    <>
      <Card job={a} k={`a-${idx}`} />
      <Card job={b} k={`b-${idx}`} />
    </>
  );
}

/* ---------- TWEAKS APPLIED AT BOOT (tweaks panel removed for production) ---------- */

/* ---------- MOUNT ---------- */
const faqRoot = document.getElementById("faq-list");
if (faqRoot) ReactDOM.createRoot(faqRoot).render(<FAQ />);

const heroRoot = document.getElementById("hero-waitlist");
if (heroRoot) ReactDOM.createRoot(heroRoot).render(<WaitlistForm variant="hero" />);
const ctaRoot = document.getElementById("cta-waitlist");
if (ctaRoot) ReactDOM.createRoot(ctaRoot).render(<WaitlistForm variant="cta" />);

const marqueeRoot = document.getElementById("marquee-track");
if (marqueeRoot) ReactDOM.createRoot(marqueeRoot).render(<Marquee />);

const phoneRoot = document.getElementById("phone-stack");
if (phoneRoot) ReactDOM.createRoot(phoneRoot).render(<PhoneCardCycler />);

applyTweaks(TWEAK_DEFAULTS);
setupThemeToggle();

/* ---------- COOKIE BANNER ---------- */
(function setupCookieBanner() {
  const banner = document.getElementById("cookieBanner");
  if (!banner) return;
  const KEY = "brigzy-cookies";
  if (localStorage.getItem(KEY)) return; // already decided
  // Reveal after a short delay so it doesn't fight the hero animation
  setTimeout(() => banner.classList.add("visible"), 1800);
  banner.querySelectorAll("[data-cookie-action]").forEach(btn => {
    btn.addEventListener("click", () => {
      const accepted = btn.getAttribute("data-cookie-action") === "accept";
      localStorage.setItem(KEY, accepted ? "accepted" : "declined");
      banner.classList.remove("visible");
    });
  });
})();

/* ---------- CURSOR SPOTLIGHT + DROPLET (SPEED) + ORB PARALLAX ---------- */
const spotlight = IS_TOUCH ? null : document.getElementById("spotlight");
const droplet = IS_TOUCH ? null : document.getElementById("droplet");
const orb1 = document.getElementById("orb-1");
const orb2 = document.getElementById("orb-2");
const phoneGlow = IS_TOUCH ? null : document.getElementById("phone-glow");
const phone = IS_TOUCH ? null : document.getElementById("phone");

let mouseX = window.innerWidth / 2;
let mouseY = window.innerHeight / 2;
let curX = mouseX, curY = mouseY;
let lastMx = mouseX, lastMy = mouseY;
let velocity = 0;
let dropletX = mouseX, dropletY = mouseY;
let dropletOpacity = 0;

document.addEventListener("mousemove", (e) => {
  const ddx = e.clientX - lastMx;
  const ddy = e.clientY - lastMy;
  const speed = Math.hypot(ddx, ddy);
  velocity = velocity * 0.7 + speed * 0.3;
  lastMx = e.clientX;
  lastMy = e.clientY;
  mouseX = e.clientX;
  mouseY = e.clientY;
  document.body.classList.add("cursor-active");
});
document.addEventListener("mouseleave", () => {
  document.body.classList.remove("cursor-active");
});

function rafLoop() {
  curX += (mouseX - curX) * 0.12;
  curY += (mouseY - curY) * 0.12;
  velocity *= 0.9;

  if (spotlight) {
    const speedScale = 1 + Math.min(velocity / 80, 0.35);
    const angle = Math.atan2(mouseY - curY, mouseX - curX) * 180 / Math.PI;
    spotlight.style.left = curX + "px";
    spotlight.style.top = curY + "px";
    spotlight.style.transform = `translate(-50%, -50%) rotate(${angle}deg) scaleX(${speedScale}) scaleY(${2 - speedScale})`;
  }

  if (droplet) {
    const targetOpacity = Math.min(velocity / 30, 0.7);
    dropletOpacity += (targetOpacity - dropletOpacity) * 0.15;
    dropletX += (mouseX - dropletX) * 0.22;
    dropletY += (mouseY - dropletY) * 0.22;
    const stretch = 1 + Math.min(velocity / 25, 1.4);
    const angle = Math.atan2(mouseY - dropletY, mouseX - dropletX) * 180 / Math.PI;
    droplet.style.left = dropletX + "px";
    droplet.style.top = dropletY + "px";
    droplet.style.opacity = dropletOpacity;
    droplet.style.transform = `translate(-50%, -50%) rotate(${angle}deg) scaleX(${stretch}) scaleY(${1 / Math.sqrt(stretch)})`;
  }

  const dx = (mouseX / window.innerWidth - 0.5);
  const dy = (mouseY / window.innerHeight - 0.5);
  if (orb1) orb1.style.transform = `translate(${dx * -40}px, ${dy * -30}px)`;
  if (orb2) orb2.style.transform = `translate(${dx * 30}px, ${dy * 40}px)`;
  if (phone && phoneGlow) {
    const r = phone.getBoundingClientRect();
    const px = (mouseX - (r.left + r.width / 2)) / (r.width / 2);
    const py = (mouseY - (r.top + r.height / 2)) / (r.height / 2);
    const inRange = Math.abs(px) < 3 && Math.abs(py) < 3;
    if (inRange) {
      phone.style.transform = `perspective(1200px) rotateY(${Math.max(-12, Math.min(12, px * 8))}deg) rotateX(${Math.max(-8, Math.min(8, -py * 6))}deg) rotate(0deg)`;
      phoneGlow.style.transform = `translate(calc(-50% + ${px * 30}px), calc(-50% + ${py * 30}px))`;
    } else {
      phone.style.transform = "";
    }
  }
  requestAnimationFrame(rafLoop);
}
if (!IS_TOUCH) rafLoop();

/* ---------- MAGNETIC NAV CTA ---------- */
(function magnetizeNavCta() {
  if (IS_TOUCH) return;
  const btn = document.querySelector(".nav-cta");
  if (!btn) return;
  const onMove = (e) => {
    const r = btn.getBoundingClientRect();
    const x = e.clientX - (r.left + r.width / 2);
    const y = e.clientY - (r.top + r.height / 2);
    const dist = Math.hypot(x, y);
    if (dist < 60) {
      btn.style.transform = `translate(${x * 0.15}px, ${y * 0.15}px)`;
    } else {
      btn.style.transform = "";
    }
  };
  const onLeave = () => { btn.style.transform = ""; };
  window.addEventListener("mousemove", onMove);
  btn.addEventListener("mouseleave", onLeave);
})();

/* ---------- 3D TILT ON CARDS ---------- */
function attachTilt(selector, intensity = 6) {
  document.querySelectorAll(selector).forEach(card => {
    card.addEventListener("mousemove", (e) => {
      const r = card.getBoundingClientRect();
      const x = (e.clientX - r.left) / r.width - 0.5;
      const y = (e.clientY - r.top) / r.height - 0.5;
      card.style.transform = `perspective(1000px) rotateY(${x * intensity}deg) rotateX(${-y * intensity}deg) translateY(-3px)`;
    });
    card.addEventListener("mouseleave", () => { card.style.transform = ""; });
  });
}
if (!IS_TOUCH) {
  attachTilt(".feature", 3);
  attachTilt(".step", 4);
}

/* ---------- PRE KOHO: CARD EXPAND/COLLAPSE ---------- */
(function setupPreKoho() {
  const cards = document.querySelectorAll(".pk-card");
  if (!cards.length) return;

  let openSide = null;

  const setState = (side, isOpen) => {
    const card = document.getElementById("pkCard" + side);
    const detail = document.getElementById("pkDetail" + side);
    if (!card || !detail) return;
    card.classList.toggle("active", isOpen);
    card.setAttribute("aria-expanded", isOpen ? "true" : "false");
    detail.classList.toggle("open", isOpen);
    if (isOpen) detail.removeAttribute("hidden");
    else detail.setAttribute("hidden", "");
  };

  const toggle = (side) => {
    const other = side === "A" ? "B" : "A";
    if (openSide === side) {
      setState(side, false);
      openSide = null;
      return;
    }
    if (openSide === other) setState(other, false);
    setState(side, true);
    openSide = side;
    // Scroll the open detail into view after the panel animates open.
    setTimeout(() => {
      const detail = document.getElementById("pkDetail" + side);
      if (detail) detail.scrollIntoView({ behavior: "smooth", block: "nearest" });
    }, 120);
  };

  cards.forEach(card => {
    const side = card.dataset.side;
    if (!side) return;
    card.addEventListener("click", () => toggle(side));
    card.addEventListener("keydown", (e) => {
      if (e.key === "Enter" || e.key === " ") {
        e.preventDefault();
        toggle(side);
      }
    });
  });

  document.querySelectorAll(".pk-close").forEach(btn => {
    btn.addEventListener("click", (e) => {
      e.stopPropagation();
      const side = btn.dataset.close;
      if (side && openSide === side) {
        setState(side, false);
        openSide = null;
      }
    });
  });

  // Waitlist CTA inside an open detail panel: do a controlled scroll instead of native anchor
  // navigation, because the open panel + the pending scrollIntoView from toggle() can interfere
  // with the browser's smooth-scroll target and the user lands short of the section.
  document.querySelectorAll(".pk-detail .pk-cta").forEach(a => {
    a.addEventListener("click", (e) => {
      e.preventDefault();
      e.stopPropagation();
      const href = a.getAttribute("href");
      const target = href && document.querySelector(href);
      if (!target) return;
      const y = target.getBoundingClientRect().top + window.scrollY;
      try { history.replaceState(null, "", href); } catch (_) {}
      window.scrollTo({ top: y, behavior: "smooth" });
    });
  });
})();

/* ---------- SCROLL REVEAL ---------- */
const sections = document.querySelectorAll("section");
sections.forEach(s => s.classList.add("reveal"));
const io = new IntersectionObserver((entries) => {
  entries.forEach(e => {
    if (e.isIntersecting) {
      e.target.classList.add("in");
      io.unobserve(e.target);
    }
  });
}, { threshold: 0.08, rootMargin: "0px 0px -60px 0px" });
sections.forEach(s => io.observe(s));
document.querySelector(".hero")?.classList.add("in");

// Play hero h1 word reveal only when page is visible (avoids paused animations leaving text hidden)
(function playHeroWords() {
  const h1 = document.querySelector(".hero h1");
  if (!h1) return;
  const start = () => h1.classList.add("anim");
  if (document.visibilityState === "visible") {
    requestAnimationFrame(start);
  } else {
    document.addEventListener("visibilitychange", () => {
      if (document.visibilityState === "visible") start();
    }, { once: true });
  }
})();
