/* global React */
const { useEffect: useEffectUI, useRef: useRefUI, useState: useStateUI } = React;

/* Resolves an asset path to an inlined blob URL when bundled (standalone),
   otherwise returns the plain relative path (live/dev). */
const ASSET = (p) => (p && window.__resources && window.__resources[p]) || p;
window.ASSET = ASSET;

/* ============== Splash SVG ============== */
function Splash({ className = "", style = {}, color = "currentColor" }) {
  return (
    <svg
      className={`splash ${className}`}
      style={style}
      viewBox="0 0 400 400"
      fill="none"
      xmlns="http://www.w3.org/2000/svg"
      aria-hidden="true"
    >
      <g fill={color}>
        <path d="M200 40c-20 0-30 22-28 42 2 18 18 28 14 46-4 18-30 22-30 44 0 26 32 30 36 56 2 18-22 28-18 50 4 24 38 30 60 18 24-12 30-46 18-66-8-14-26-18-26-36 0-22 30-26 32-50 2-22-22-30-24-52-2-20 16-30 14-48-2-18-22-26-48-4z"/>
        <circle cx="80" cy="120" r="14"/>
        <circle cx="320" cy="100" r="8"/>
        <circle cx="60" cy="280" r="10"/>
        <circle cx="340" cy="300" r="12"/>
        <circle cx="100" cy="60" r="6"/>
        <circle cx="280" cy="350" r="6"/>
        <path d="M40 180c10-4 22-2 24 8 2 8-8 14-18 12-12-2-14-16-6-20z"/>
        <path d="M360 200c-10-2-20 6-18 16 2 8 16 10 22 2 6-8 4-16-4-18z"/>
        <path d="M200 380c12 4 22-6 18-16-4-10-22-8-24 2-2 8 2 12 6 14z"/>
        <path d="M120 360c-8-2-16 4-14 12 2 6 12 8 16 2 4-6 2-12-2-14z"/>
        <circle cx="200" cy="20" r="4"/>
        <circle cx="20" cy="200" r="4"/>
        <circle cx="380" cy="200" r="4"/>
      </g>
    </svg>
  );
}

/* ============== Logo ============== */
function Logo({ height = 46, onClick }) {
  return (
    <div className="header__logo" onClick={onClick} role="button" aria-label="Holy Smash — Startseite">
      <img src={ASSET("assets-min/logo.webp")} alt="Holy Smash Burgers" style={{ height }} />
    </div>
  );
}

/* ============== Smash Button ============== */
function Btn({ children, variant = "primary", size = "", onClick, href, ...rest }) {
  const cls = `btn btn--${variant} ${size ? `btn--${size}` : ""}`;
  if (href) {
    return (
      <a className={cls} href={href} target="_blank" rel="noreferrer" {...rest}>
        <span>{children}</span>
      </a>
    );
  }
  return (
    <button className={cls} onClick={onClick} {...rest}>
      <span>{children}</span>
    </button>
  );
}

async function sendHolyForm(kind, data) {
  const res = await fetch("/api/contact", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ kind, ...data })
  });
  let payload = {};
  try {
    payload = await res.json();
  } catch (_) {}
  if (!res.ok || !payload.ok) {
    throw new Error(payload.error || "Die Nachricht konnte nicht gesendet werden.");
  }
  return payload;
}

const HOLY_FALLBACK_EVENTS = [
  {
    id: "fallback-stammplatz",
    title: "Holy Smash Truck · Stammplatz Bamenohl",
    location: "Schützenhalle Bamenohl, Bamenohler Str. 55, 57413 Finnentrop",
    start: "2026-01-02T17:00:00+01:00",
    end: "2026-01-02T21:00:00+01:00",
    dayNumber: "2",
    month: "Jan",
    weekday: "Fr",
    startTime: "17:00",
    endTime: "21:00",
    tag: "Stammplatz",
    meta: "Stammplatz · Parken vor Ort",
    mapsUrl: "https://maps.google.com/?q=Sch%C3%BCtzenhalle+Bamenohl"
  }
];

function useHolyEvents(limit = 24) {
  const [events, setEvents] = React.useState(HOLY_FALLBACK_EVENTS);
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState("");

  React.useEffect(() => {
    let cancelled = false;
    setLoading(true);
    fetch(`/api/events?limit=${limit}`)
      .then((res) => res.ok ? res.json() : Promise.reject(new Error("Termine konnten nicht geladen werden.")))
      .then((payload) => {
        if (cancelled) return;
        if (payload.ok && payload.events && payload.events.length) {
          setEvents(payload.events);
          setError("");
        }
      })
      .catch((err) => {
        if (!cancelled) setError(err.message || "Termine konnten nicht geladen werden.");
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => { cancelled = true; };
  }, [limit]);

  return { events, loading, error };
}

function eventLocationTitle(event) {
  if (!event) return "Holy Smash Truck";
  if ((event.location || "").includes("Schützenhalle") || (event.location || "").includes("Bamenohl")) return "Schützenhalle Bamenohl";
  return event.title || "Holy Smash Truck";
}

function useInstagramFeed(limit = 6) {
  const [posts, setPosts] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [configured, setConfigured] = React.useState(false);
  const [error, setError] = React.useState("");

  React.useEffect(() => {
    let cancelled = false;
    setLoading(true);
    fetch(`/api/instagram?limit=${limit}`)
      .then((res) => res.ok ? res.json() : Promise.reject(new Error("Instagram Feed konnte nicht geladen werden.")))
      .then((payload) => {
        if (cancelled) return;
        setConfigured(Boolean(payload.configured));
        if (payload.ok && payload.posts?.length) {
          setPosts(payload.posts);
          setError("");
        } else {
          setPosts([]);
          setError(payload.error || "Instagram Feed ist noch nicht verbunden.");
        }
      })
      .catch((err) => {
        if (!cancelled) setError(err.message || "Instagram Feed konnte nicht geladen werden.");
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => { cancelled = true; };
  }, [limit]);

  return { posts, loading, configured, error };
}

/* ============== Food placeholder ============== */
function Food({ label, sub, hand, badges = [], wide = false, palette = "teal", img, video }) {
  const colors = {
    teal: "#3dd6d0",
    orange: "#f4a340",
    red: "#e63946",
  };
  if (img || video) {
    return (
      <div className={`food food--photo ${wide ? "food--wide" : ""}`}>
        {video ? (
          <video
            ref={(el) => {
              if (!el) return;
              el.muted = true;
              const tryPlay = () => {
                const p = el.play();
                if (p && p.catch) p.catch(() => {});
              };
              if (el.readyState >= 2) tryPlay();
              else el.addEventListener("canplay", tryPlay, { once: true });
            }}
            className="food__img"
            src={ASSET(video)}
            poster={img ? ASSET(img) : undefined}
            autoPlay
            muted
            loop
            playsInline
            preload="auto"
            aria-label={label}
          />
        ) : (
          <img className="food__img" src={ASSET(img)} alt={label} loading="lazy" />
        )}
        {hand && <div className="food__hand">{hand}</div>}
        {badges.length > 0 && (
          <div className="card__badges">
            {badges.map((b, i) => (
              <span key={i} className={`tape tape--${b.kind || "teal"}`} style={{ transform: `rotate(${i % 2 ? 2 : -2}deg)` }}>
                {b.text}
              </span>
            ))}
          </div>
        )}
      </div>
    );
  }
  return (
    <div className={`food ${wide ? "food--wide" : ""}`}>
      <Splash className="food__splash" color={colors[palette] || colors.teal} />
      <div className="food__disc" />
      <div className="food__stripe" />
      {hand && <div className="food__hand">{hand}</div>}
      <div className="food__label">
        <div className="left">
          <span>{label}</span>
          {sub && <span style={{ opacity: 0.6 }}>{sub}</span>}
        </div>
        <span>HOLY //</span>
      </div>
      {badges.length > 0 && (
        <div className="card__badges">
          {badges.map((b, i) => (
            <span key={i} className={`tape tape--${b.kind || "teal"}`} style={{ transform: `rotate(${i % 2 ? 2 : -2}deg)` }}>
              {b.text}
            </span>
          ))}
        </div>
      )}
    </div>
  );
}

/* ============== Marquee ============== */
function Marquee({ items, variant = "default" }) {
  const repeated = [...items, ...items];
  return (
    <div className={`marquee ${variant === "teal" ? "marquee--teal" : ""}`}>
      <div className="marquee__track">
        {repeated.map((item, i) => (
          <span key={i} className="marquee__item">
            {item}
            <span className="dot" />
          </span>
        ))}
      </div>
    </div>
  );
}

/* ============== Scroll reveal ============== */
function Reveal({ children, as: As = "div", className = "", staggerChildren = false, ...rest }) {
  const ref = useRefUI(null);
  const [seen, setSeen] = useStateUI(false);
  useEffectUI(() => {
    if (!ref.current) return;
    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) {
            setSeen(true);
            io.disconnect();
          }
        });
      },
      { threshold: 0.12, rootMargin: "0px 0px -40px 0px" }
    );
    io.observe(ref.current);
    return () => io.disconnect();
  }, []);
  const base = staggerChildren ? "reveal-children" : "reveal";
  return (
    <As ref={ref} className={`${base} ${seen ? "in" : ""} ${className}`} {...rest}>
      {children}
    </As>
  );
}

/* ============== Section header ============== */
function SectionHead({ eyebrow, title, sub }) {
  return (
    <Reveal className="section-head">
      <div>
        {eyebrow && <div className="eyebrow" style={{ marginBottom: 14 }}>{eyebrow}</div>}
        <h2 className="section-head__title display">{title}</h2>
      </div>
      {sub && <p className="section-head__sub">{sub}</p>}
    </Reveal>
  );
}

/* ============== Custom cursor (desktop, dezent) ============== */
function CustomCursor() {
  const dotRef = useRefUI(null);
  const ringRef = useRefUI(null);
  useEffectUI(() => {
    if (window.matchMedia("(hover: none)").matches) return;
    let x = 0, y = 0, rx = 0, ry = 0;
    let raf;
    const onMove = (e) => {
      x = e.clientX;
      y = e.clientY;
      if (dotRef.current) {
        dotRef.current.style.transform = `translate(${x - 4}px, ${y - 4}px)`;
      }
    };
    const tick = () => {
      rx += (x - rx) * 0.18;
      ry += (y - ry) * 0.18;
      if (ringRef.current) {
        ringRef.current.style.transform = `translate(${rx - 16}px, ${ry - 16}px)`;
      }
      raf = requestAnimationFrame(tick);
    };
    window.addEventListener("mousemove", onMove);
    tick();
    return () => {
      window.removeEventListener("mousemove", onMove);
      cancelAnimationFrame(raf);
    };
  }, []);

  return (
    <>
      <div
        ref={dotRef}
        style={{
          position: "fixed",
          top: 0,
          left: 0,
          width: 8,
          height: 8,
          borderRadius: "50%",
          background: "var(--teal)",
          pointerEvents: "none",
          zIndex: 9999,
          mixBlendMode: "difference",
        }}
      />
      <div
        ref={ringRef}
        style={{
          position: "fixed",
          top: 0,
          left: 0,
          width: 32,
          height: 32,
          borderRadius: "50%",
          border: "1px solid rgba(61, 214, 208, 0.4)",
          pointerEvents: "none",
          zIndex: 9999,
          transition: "width 0.2s, height 0.2s",
        }}
      />
    </>
  );
}

Object.assign(window, { Splash, Logo, Btn, Food, Marquee, Reveal, SectionHead, CustomCursor });
