/* ============ Yhden miehen levyraati — reusable components ============ */

/* ---- Logo: official Yhden miehen levyraati vinyl mark ---- */
function Logo({ size = 84 }) {
  return (
    <img
      src="assets/yml-logo.png"
      width={size}
      height={size}
      alt="Yhden miehen levyraati"
      style={{ display: "block", borderRadius: "50%" }} />
  );
}

/* ---- Album cover with vinyl disc emerging from the right edge ---- */
function AlbumCover({ review, size = "md", style = "vinyl-right" }) {
  const sz = size === "lg" ? 460 : size === "sm" ? 200 : 280;
  const hue = review?.coverHue ?? 30;
  const label = review?.work || "album";
  const id = React.useId().replace(/:/g, "");

  if (review?.cardImg) {
    return (
      <div style={{ width: "100%" }}>
        <img
          src={review.cardImg}
          alt={`${review.artist} – ${review.work}`}
          style={{ width: "100%", height: "auto", display: "block", borderRadius: 4 }} />
      </div>
    );
  }

  return (
    <div style={{ width: sz * 1.35, maxWidth: "100%" }}>
      <svg viewBox="0 0 270 200" width="100%" role="img" aria-label={`Cover: ${label}`}>
        <defs>
          <linearGradient id={`bg-${id}`} x1="0" x2="1" y1="0" y2="1">
            <stop offset="0%" stopColor={`oklch(0.7 0.14 ${hue})`} />
            <stop offset="100%" stopColor={`oklch(0.42 0.12 ${hue})`} />
          </linearGradient>
          <pattern id={`stripes-${id}`} patternUnits="userSpaceOnUse" width="14" height="14" patternTransform="rotate(45)">
            <rect width="14" height="14" fill={`oklch(0.62 0.13 ${hue})`} />
            <rect width="7" height="14" fill={`oklch(0.55 0.13 ${hue})`} />
          </pattern>
          <clipPath id={`cover-clip-${id}`}>
            <rect x="0" y="0" width="200" height="200" />
          </clipPath>
        </defs>

        {/* Vinyl disc — peeks out of right edge of cover */}
        <g transform="translate(195, 100)">
          <circle r="92" fill="#0d0d0d" />
          <circle r="88" fill="none" stroke="#1a1a1a" strokeWidth="1" />
          <circle r="78" fill="none" stroke="#1a1a1a" strokeWidth="0.6" />
          <circle r="68" fill="none" stroke="#1a1a1a" strokeWidth="0.6" />
          <circle r="58" fill="none" stroke="#1a1a1a" strokeWidth="0.6" />
          <circle r="48" fill="none" stroke="#1a1a1a" strokeWidth="0.6" />
          <circle r="38" fill="none" stroke="#1a1a1a" strokeWidth="0.6" />
          <circle r="30" fill={`oklch(0.55 0.13 ${hue})`} />
          <circle r="3" fill="#000" />
          <ellipse cx="-30" cy="-40" rx="36" ry="10" fill="rgba(255,255,255,0.05)" transform="rotate(-30)" />
        </g>

        {/* Cover artwork on top */}
        <g clipPath={`url(#cover-clip-${id})`}>
          <rect x="0" y="0" width="200" height="200" fill={`url(#bg-${id})`} />
          <rect x="0" y="0" width="200" height="200" fill={`url(#stripes-${id})`} opacity="0.25" />
          <circle cx={50 + hue % 40} cy={70 + hue % 30} r="36" fill={`oklch(0.85 0.13 ${hue})`} opacity="0.55" />
          <rect x={100} y={120} width="60" height="60" fill={`oklch(0.25 0.05 ${hue})`} opacity="0.6" />
          <text x="14" y="180" fill="rgba(255,255,255,0.9)" fontFamily="Calistoga, serif" fontSize="18">
            {(review?.artist || "Artist").slice(0, 18)}
          </text>
          <text x="14" y="196" fill="rgba(255,255,255,0.7)" fontFamily="Familjen Grotesk, sans-serif" fontSize="10" letterSpacing="1.5">
            {(review?.work || "Work").toUpperCase().slice(0, 28)}
          </text>
        </g>
        <rect x="0" y="0" width="200" height="200" fill="none" stroke="#000" strokeWidth="1.5" />
      </svg>
    </div>
  );
}

/* ---- Concert ticket frame ---- */
function ConcertTicket({ concert, size = "md" }) {
  const sz = size === "lg" ? 480 : size === "sm" ? 220 : 300;
  const hue = concert?.coverHue ?? 20;
  const id = React.useId().replace(/:/g, "");

  if (concert?.cardImg) {
    return (
      <div style={{ width: "100%" }}>
        <img
          src={concert.cardImg}
          alt={`${concert.artist} @ ${concert.venue}`}
          style={{ width: "100%", height: "auto", display: "block", borderRadius: 4 }} />
      </div>
    );
  }

  return (
    <div style={{ width: sz, maxWidth: "100%" }}>
      <svg viewBox="0 0 300 220" width="100%" role="img" aria-label={`Ticket: ${concert?.artist}`}>
        <defs>
          <pattern id={`ticket-tex-${id}`} patternUnits="userSpaceOnUse" width="8" height="8">
            <rect width="8" height="8" fill="#E27A66" />
            <circle cx="4" cy="4" r="0.6" fill="#B4513F" opacity="0.3" />
          </pattern>
          <clipPath id={`art-clip-${id}`}>
            <rect x="14" y="14" width="220" height="192" rx="2" />
          </clipPath>
        </defs>

        {/* Drop shadow */}
        <path d="M 6,16 L 246,16 a 6,6 0 0 1 6,6 L 252,80 a 6,6 0 0 0 0,12 L 252,200 a 6,6 0 0 1 -6,6 L 6,206 a 6,6 0 0 1 -6,-6 L 0,92 a 6,6 0 0 0 0,-12 L 0,22 a 6,6 0 0 1 6,-6 Z"
          transform="translate(8,8)" fill="#7E2A1B" opacity="0.4" />

        {/* Main ticket body */}
        <path d="M 6,4 L 246,4 a 6,6 0 0 1 6,6 L 252,68 a 6,6 0 0 0 0,12 L 252,188 a 6,6 0 0 1 -6,6 L 6,194 a 6,6 0 0 1 -6,-6 L 0,80 a 6,6 0 0 0 0,-12 L 0,10 a 6,6 0 0 1 6,-6 Z"
          fill={`url(#ticket-tex-${id})`} stroke="#000" strokeWidth="2" />

        {/* Perforation line */}
        <line x1="252" y1="20" x2="252" y2="180" stroke="#000" strokeWidth="1.5" strokeDasharray="3 4" />

        {/* Stub - right side */}
        <g>
          <text x="272" y="50" fill="#000" fontFamily="Familjen Grotesk, sans-serif" fontSize="10" letterSpacing="2" transform="rotate(90 272 50)">
            ADMIT ONE
          </text>
          <text x="282" y="40" fill="#000" fontFamily="Calistoga, serif" fontSize="28" fontWeight="bold" transform="rotate(90 282 40)">
            72411
          </text>
        </g>

        {/* Cover art on left side */}
        <g clipPath={`url(#art-clip-${id})`}>
          <rect x="14" y="14" width="220" height="192" fill={`oklch(0.55 0.14 ${hue})`} />
          <rect x="14" y="14" width="220" height="192" fill={`oklch(0.35 0.08 ${hue})`} opacity="0.5" />
          <ellipse cx="80" cy="60" rx="60" ry="30" fill={`oklch(0.85 0.14 ${hue})`} opacity="0.45" />
          <ellipse cx="180" cy="80" rx="60" ry="30" fill={`oklch(0.85 0.14 ${hue + 30})`} opacity="0.4" />
          <rect x="40" y="130" width="170" height="80" fill="#000" opacity="0.65" />
          <circle cx="80" cy="130" r="14" fill="#000" opacity="0.8" />
          <circle cx="140" cy="125" r="14" fill="#000" opacity="0.8" />
          <circle cx="190" cy="135" r="14" fill="#000" opacity="0.8" />
        </g>
        <rect x="14" y="14" width="220" height="192" fill="none" stroke="#000" strokeWidth="1.5" />

        {/* Title strip */}
        <rect x="14" y="170" width="220" height="36" fill="rgba(0,0,0,0.7)" />
        <text x="24" y="186" fill="#fff" fontFamily="Calistoga, serif" fontSize="13">
          {(concert?.artist || "Artist").slice(0, 24)}
        </text>
        <text x="24" y="200" fill="#FFBD59" fontFamily="Familjen Grotesk, sans-serif" fontSize="9" letterSpacing="1.2">
          {(concert?.venue || "").toUpperCase()} · {(concert?.city || "").toUpperCase()} · {concert?.concertDate}
        </text>
      </svg>
    </div>
  );
}

/* ---- Header ---- */
function Header({ route, navigate }) {
  const [open, setOpen] = React.useState(false);
  const items = [
    { id: "home", label: "Etusivu" },
    { id: "podcast", label: "Podcast" },
    { id: "levyarviot", label: "Levyarviot" },
    { id: "keikkaraportit", label: "Keikkaraportit" },
    { id: "_brs", label: "Bad Record Store", external: true, href: "https://www.badrecordstore.fi/?ref=yhdenmiehenlevyraati" },
    { id: "info", label: "Info" },
    { id: "yhteys", label: "Yhteys" },
  ];

  const activeRoot = route.split("/")[0];

  return (
    <header className="header">
      <a className="skip-link" href="#main">Siirry sisältöön</a>
      <div className="header__inner">
        <a onClick={() => { navigate("home"); setOpen(false); }} style={{ display: "flex", alignItems: "center", gap: 12, textDecoration: "none", cursor: "pointer" }}>
          <Logo size={120} />
          <span style={{ fontFamily: "var(--font-heading)", fontSize: "1.05rem", lineHeight: 1.05, maxWidth: 130, display: "none" }}>
            Yhden miehen<br />levyraati
          </span>
        </a>
        <button className="header__hamburger" onClick={() => setOpen((o) => !o)} aria-label="Valikko">
          {open ? "Sulje" : "Valikko"} ☰
        </button>
        <nav className={"header__nav" + (open ? " is-open" : "")} aria-label="Päävalikko">
          {items.map((it) => it.external
            ? <a key={it.id} href={it.href} target="_blank" rel="noopener">{it.label}</a>
            : <a key={it.id}
                className={activeRoot === it.id ? "is-active" : ""}
                onClick={() => { navigate(it.id); setOpen(false); }}>
                {it.label}
              </a>
          )}
        </nav>
      </div>
    </header>
  );
}

/* ---- Footer ---- */
function Footer({ navigate }) {
  return (
    <footer className="footer">
      <div className="container">
        <div className="footer__row">
          <div>
            <div style={{ fontFamily: "var(--font-heading)", fontSize: "1.25rem", marginBottom: 8 }}>Yhden miehen levyraati</div>
            <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-start", gap: 4 }}>
              <button className="btn btn--tertiary" style={{ padding: 0 }} onClick={() => navigate("tietosuojaseloste")}>Tietosuojaseloste</button>
              <button className="btn btn--tertiary" style={{ padding: 0 }} onClick={() => window.openCookiePreferences()}>Evästeasetukset</button>
            </div>
          </div>
          <div className="footer__icons">
            <a className="footer__icon" href="https://open.spotify.com/show/3TcraLNC3FwD9Z3gta9bHZ" target="_blank" rel="noopener" aria-label="Spotify">
              <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0a12 12 0 1 0 0 24 12 12 0 0 0 0-24Zm5.5 17.3a.75.75 0 0 1-1 .25c-2.75-1.7-6.2-2.1-10.3-1.15a.75.75 0 1 1-.3-1.45c4.45-1 8.25-.55 11.3 1.35a.75.75 0 0 1 .3 1Zm1.45-3.25a.93.93 0 0 1-1.3.3c-3.15-1.95-7.95-2.5-11.7-1.4a.93.93 0 0 1-.55-1.8c4.25-1.25 9.55-.65 13.2 1.6a.93.93 0 0 1 .35 1.3Zm.15-3.4c-3.75-2.25-9.95-2.45-13.55-1.35a1.1 1.1 0 1 1-.65-2.1c4.15-1.25 11-1 15.35 1.55a1.1 1.1 0 1 1-1.15 1.9Z" /></svg>
            </a>
            <a className="footer__icon" href="https://www.instagram.com/yhdenmiehenlevyraati/" target="_blank" rel="noopener" aria-label="Instagram">
              <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="3" width="18" height="18" rx="5" /><circle cx="12" cy="12" r="4" /><circle cx="17.5" cy="6.5" r="1.2" fill="currentColor" /></svg>
            </a>
            <a className="footer__icon" href="https://www.youtube.com/@yhdenmiehenlevyraati" target="_blank" rel="noopener" aria-label="YouTube">
              <svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M21.8 8s-.2-1.4-.8-2a2.9 2.9 0 0 0-2-.8C17.2 5 12 5 12 5s-5.2 0-7 .2a2.9 2.9 0 0 0-2 .8C2.4 6.6 2.2 8 2.2 8S2 9.6 2 11.2v1.5c0 1.6.2 3.2.2 3.2s.2 1.4.8 2a3 3 0 0 0 2 .8c1.6.2 6.8.2 7 .2s5.2 0 7-.2a2.9 2.9 0 0 0 2-.8c.6-.6.8-2 .8-2S22 14.3 22 12.7v-1.5C22 9.6 21.8 8 21.8 8zM10 15V9l5.5 3-5.5 3z"/></svg>
            </a>
            <a className="footer__icon" href="mailto:yhdenmiehenlevyraati@gmail.com" aria-label="Email">
              <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><rect x="3" y="5" width="18" height="14" rx="2" /><path d="M3 7l9 7 9-7" /></svg>
            </a>
          </div>
          <div className="footer__right">
            <a href="mailto:yhdenmiehenlevyraati@gmail.com" style={{ textDecoration: "underline", textUnderlineOffset: 4 }}>
              yhdenmiehenlevyraati@gmail.com
            </a>
          </div>
        </div>
        <div className="footer__bottom">
          <div>© Yhden miehen levyraati 2026</div>
        </div>
      </div>
    </footer>
  );
}

/* ---- Article card ---- */
function ReviewCard({ review, navigate }) {
  return (
    <a className="article-card" onClick={() => navigate(`levyarviot/${review.slug}`)}>
      <AlbumCover review={review} />
      <div className="article-card__date">{review.dateShort}</div>
      <h3 className="article-card__title">{review.title}</h3>
      <span className="article-card__link">Lue lisää →</span>
    </a>
  );
}

function ConcertCard({ concert, navigate }) {
  return (
    <a className="article-card" onClick={() => navigate(`keikkaraportit/${concert.slug}`)}>
      <ConcertTicket concert={concert} />
      <div className="article-card__date">{concert.dateShort}</div>
      <h3 className="article-card__title">{concert.title}</h3>
      <span className="article-card__link">Lue lisää →</span>
    </a>
  );
}

/* ---- Bad Record Store promo ---- */
function BadRecordPromo() {
  return (
    <div className="promo">
      <span className="eyebrow" style={{ color: "var(--yellow)" }}>Yhteistyössä</span>
      <h3>Levyt omaksi?</h3>
      <p style={{ maxWidth: "44ch", margin: 0, lineHeight: 1.5 }}>
        Koodilla <span className="promo__code">YML15</span> &nbsp;saat <strong>-15 %</strong> kaikista tuotteista ensimmäisellä ostoksellasi.
      </p>
      <a className="btn btn--primary" href="https://www.badrecordstore.fi/?ref=yhdenmiehenlevyraati" target="_blank" rel="noopener">
        Bad Record Store →
      </a>
    </div>
  );
}

/* ---- Instagram feed (live grid via /api/instagram, falls back to placeholders) ---- */
function getPostImage(post) {
  if (post.media_type === "VIDEO") return post.thumbnail_url || null;
  return post.media_url || post.thumbnail_url || null;
}

function InstagramGrid() {
  const [posts, setPosts] = React.useState(null); // null = still loading

  React.useEffect(() => {
    fetch("/api/instagram")
      .then((r) => r.json())
      .then((data) => setPosts(Array.isArray(data.data) ? data.data : []))
      .catch(() => setPosts([]));
  }, []);

  const realPhotos = [
    "assets/ig/ig-1.jpg",
    "assets/ig/ig-2.jpg",
    "assets/ig/ig-3.jpg",
    "assets/ig/ig-4.jpg",
    "assets/ig/ig-5.jpg",
    "assets/ig/ig-6.jpg",
  ];
  const profileUrl = "https://www.instagram.com/yhdenmiehenlevyraati/";

  const tiles = Array.from({ length: 9 }, (_, i) => {
    const post = posts && posts[i];
    if (post) {
      return { photo: getPostImage(post), link: post.permalink || profileUrl, hue: i * 41 % 360 };
    }
    // While loading (posts === null) show the local placeholder photos;
    // once loaded, any slot without a real post falls back to a plain tile.
    return { photo: posts === null ? realPhotos[i] || null : null, link: profileUrl, hue: i * 41 % 360 };
  });

  return (
    <div className="ig-grid">
      {tiles.map((t, i) =>
        <a key={i} className="ig-tile" href={t.link} target="_blank" rel="noopener"
          style={t.photo ? {} : {
            background: `linear-gradient(135deg, oklch(0.55 0.13 ${t.hue}), oklch(0.32 0.1 ${t.hue + 30}))`
          }}>
          {t.photo &&
            <img src={t.photo} alt="" style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }} />
          }
          <div style={{
            position: "absolute", inset: 0,
            display: "flex", alignItems: "flex-end", padding: 10,
            color: "rgba(255,255,255,0.9)", fontFamily: "Calistoga, serif", fontSize: "0.9rem",
            background: t.photo ? "linear-gradient(to top, rgba(0,0,0,0.55) 0%, transparent 50%)" : "none",
          }}>
            @yhdenmiehenlevyraati
          </div>
        </a>
      )}
    </div>
  );
}

/* ---- Contact form ---- */
function ContactForm() {
  const [form, setForm] = React.useState({ firstName: "", lastName: "", email: "", message: "", honeypot: "" });
  const [status, setStatus] = React.useState("idle"); // idle | sending | sent | error

  function update(field) {
    return (e) => setForm((f) => ({ ...f, [field]: e.target.value }));
  }

  async function submit(e) {
    e.preventDefault();
    setStatus("sending");
    try {
      const res = await fetch("/api/contact", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(form),
      });
      if (!res.ok) throw new Error("Lähetys epäonnistui");
      setStatus("sent");
      setForm({ firstName: "", lastName: "", email: "", message: "", honeypot: "" });
      setTimeout(() => setStatus("idle"), 4000);
    } catch (err) {
      setStatus("error");
    }
  }

  return (
    <form onSubmit={submit} style={{ display: "flex", flexDirection: "column", gap: 18 }}>
      <div className="form-row">
        <div className="field">
          <label>Etunimi *</label>
          <input required type="text" value={form.firstName} onChange={update("firstName")} />
        </div>
        <div className="field">
          <label>Sukunimi *</label>
          <input required type="text" value={form.lastName} onChange={update("lastName")} />
        </div>
      </div>
      <div className="field">
        <label>Email *</label>
        <input required type="email" value={form.email} onChange={update("email")} />
      </div>
      <div className="field">
        <label>Viesti *</label>
        <textarea required rows="5" value={form.message} onChange={update("message")}></textarea>
      </div>
      <div className="field field--honeypot">
        <label>Älä täytä</label>
        <input type="text" tabIndex="-1" autoComplete="off" value={form.honeypot} onChange={update("honeypot")} />
      </div>
      <button type="submit" className="btn btn--primary" style={{ alignSelf: "flex-start" }} disabled={status === "sending"}>
        {status === "sent" ? "Kiitos viestistäsi! ✓" : status === "sending" ? "Lähetetään…" : "Lähetä"}
      </button>
      {status === "error" &&
      <p style={{ color: "var(--ticket-shadow)", fontSize: "0.9rem" }}>
          Viestin lähetys epäonnistui. Yritä hetken kuluttua uudelleen tai lähetä sähköpostia suoraan osoitteeseen{" "}
          <a href="mailto:yhdenmiehenlevyraati@gmail.com" style={{ textDecoration: "underline" }}>yhdenmiehenlevyraati@gmail.com</a>.
        </p>
      }
    </form>
  );
}

/* ---- Spotify embed (real iframe for podcast show and albums; placeholder as fallback) ---- */
function SpotifyEmbed({ showId, embedUrl, type = "show", height = 232 }) {
  const consent = useCookieConsent();
  const src = type === "show" ?
  `https://open.spotify.com/embed/show/${showId}?utm_source=generator` :
  embedUrl;

  if (src && consent && consent.embeds) {
    return (
      <div className="spotify-embed" style={{ height, borderRadius: 12, overflow: "hidden", border: "2px solid var(--black)" }}>
        <iframe
          src={src}
          width="100%"
          height={height}
          frameBorder="0"
          allow="autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture"
          loading="lazy"
          title="Yhden miehen levyraati — Spotify"
          style={{ display: "block", border: "none" }}
        />
      </div>
    );
  }

  /* Embed exists but the user hasn't consented to third-party cookies yet */
  if (src) {
    return (
      <div className="spotify-embed" style={{ height, padding: 24, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 14, textAlign: "center", color: "#fff" }}>
        <div>Tämä sisältö on Spotifyn upottama soitin, joka vaatii evästeiden hyväksymisen.</div>
        <button className="btn btn--primary" style={{ background: "#1ed760", color: "#000" }} onClick={() => window.setCookieConsent({ embeds: true })}>
          Salli upotukset
        </button>
      </div>
    );
  }

  /* Fallback placeholder — no embed URL available for this album yet */
  return (
    <div className="spotify-embed" style={{ height, padding: 16, display: "flex", flexDirection: "column", justifyContent: "space-between", color: "#fff" }}>
      <div style={{ display: "flex", gap: 14, alignItems: "center" }}>
        <div style={{ width: 64, height: 64, background: "#1ed760", borderRadius: 8, display: "flex", alignItems: "center", justifyContent: "center" }}>
          <svg width="36" height="36" viewBox="0 0 24 24" fill="#000"><path d="M12 0a12 12 0 1 0 0 24 12 12 0 0 0 0-24Zm5.5 17.3a.75.75 0 0 1-1 .25c-2.75-1.7-6.2-2.1-10.3-1.15a.75.75 0 1 1-.3-1.45c4.45-1 8.25-.55 11.3 1.35a.75.75 0 0 1 .3 1Zm1.45-3.25a.93.93 0 0 1-1.3.3c-3.15-1.95-7.95-2.5-11.7-1.4a.93.93 0 0 1-.55-1.8c4.25-1.25 9.55-.65 13.2 1.6a.93.93 0 0 1 .35 1.3Zm.15-3.4c-3.75-2.25-9.95-2.45-13.55-1.35a1.1 1.1 0 1 1-.65-2.1c4.15-1.25 11-1 15.35 1.55a1.1 1.1 0 1 1-1.15 1.9Z" /></svg>
        </div>
        <div>
          <div style={{ fontFamily: "var(--font-heading)", fontSize: "1.1rem" }}>Kuuntele Spotifyssa</div>
          <div style={{ fontSize: "0.85rem", color: "#aaa" }}>open.spotify.com</div>
        </div>
        <div style={{ marginLeft: "auto" }}>
          <a href="https://open.spotify.com/show/3TcraLNC3FwD9Z3gta9bHZ" target="_blank" rel="noopener"
            style={{ background: "#1ed760", color: "#000", borderRadius: 9999, padding: "8px 18px", fontWeight: 600, textDecoration: "none", fontFamily: "inherit", fontSize: "0.9rem" }}>
            ▶ Avaa
          </a>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  Logo, AlbumCover, ConcertTicket,
  Header, Footer,
  ReviewCard, ConcertCard,
  BadRecordPromo, InstagramGrid, ContactForm, SpotifyEmbed,
});
