/* ============================================================
   Financieel Perspectief — core data, audio player, shared UI
   ============================================================ */

/* ---------- DATA ---------- */
// Real episodes. Newest first — EPISODES[0] is the featured "Nieuwste aflevering".
// Audio lives in assets/audio/ (AAC .m4a). Swap the `audio:` field to replace an episode.
const EPISODES = [
  {
    id: "ep3", num: "03", title: "Why AI Markets Mimic Telecom Bubbles",
    desc: "Torenhoge AI-waarderingen voelen verdacht vertrouwd aan. We leggen ze naast de telecombubbel van eind jaren '90 — welke parallellen hout snijden, en welke vals alarm zijn.",
    date: "20 mei 2026", dur: "20 min",
    audio: "assets/audio/why-ai-markets-mimic-telecom-bubbles.m4a",
  },
  {
    id: "ep2", num: "02", title: "Oil Matters More Than Military Scale",
    desc: "Waarom de olieprijs vaak meer over een conflict vertelt dan het aantal manschappen of tanks. Energie als de échte hefboom achter geopolitiek — en achter je portefeuille.",
    date: "22 apr 2026", dur: "21 min",
    audio: "assets/audio/oil-matters-more-than-military-scale.m4a",
  },
  {
    id: "ep1", num: "01", title: "Export Exposure Drove 2025 Market Losses",
    desc: "De marktverliezen van 2025 ontrafeld: hoe blootstelling aan export — niet de binnenlandse vraag — de grootste klappen uitdeelde, en wat dat betekent voor wie vandaag belegt.",
    date: "18 mrt 2026", dur: "14 min",
    audio: "assets/audio/export-exposure-drove-2025-market-losses.m4a",
  },
];

const HOSTS = [
  {
    initials: "WS", name: "Werner Smets", role: "Oprichter & hoofdstrateeg",
    bio: "Stuurt Vector al ruim 25 jaar door de woelige wateren van de aandelenmarkt. Bedenker van het transparante scoremodel.",
  },
  {
    initials: "TV", name: "Thierry Vandeghinste", role: "Medeoprichter & fondsbeheerder",
    bio: "Vertaalt het model naar de portefeuille — en houdt het hoofd koel wanneer de markt dat juist niet doet.",
  },
  {
    initials: "NL", name: "Nils", role: "Analist & co-host",
    bio: "Stelt de vragen die élke belegger zich stelt, en laat geen enkele aanname onbevraagd passeren.",
  },
];

const ABOUT = {
  eyebrow: "Over de podcast",
  title: "Heldere kijk op investeren & vermogen — recht uit de cockpit van Vector.",
  lead: "In Financieel Perspectief nemen de strategen van Vector je mee achter de schermen van systematisch beleggen. Elke aflevering ontleden we één thema dat élke belegger raakt — van AI-zeepbellen en de olieprijs tot de blootstelling die markten echt beweegt. Geen black-box, geen jargon om het jargon. Gewoon helder, onderbouwd, en af en toe met een knipoog.",
  stats: [
    { n: "03", u: "", l: "Afleveringen, en we zijn net begonnen" },
    { n: "25", u: "jr", l: "Beleggingservaring aan tafel" },
    { n: "2.500", u: "+", l: "Bedrijven die we wekelijks scoren" },
  ],
};

window.POD = { EPISODES, HOSTS, ABOUT };

/* ---------- ICONS (Lucide-style line glyphs) ---------- */
function Ic({ name, size = 18 }) {
  const p = {
    play: <path d="M6 4l13 8-13 8V4z" fill="currentColor" stroke="none" />,
    pause: <g fill="currentColor" stroke="none"><rect x="6" y="4" width="4" height="16" rx="1" /><rect x="14" y="4" width="4" height="16" rx="1" /></g>,
    "arrow-right": <g><path d="M5 12h14" /><path d="M13 6l6 6-6 6" /></g>,
    "arrow-up-right": <g><path d="M7 17L17 7" /><path d="M8 7h9v9" /></g>,
    headphones: <g><path d="M3 14v-2a9 9 0 0 1 18 0v2" /><path d="M21 16a2 2 0 0 1-2 2h-1v-6h1a2 2 0 0 1 2 2v2zM3 16a2 2 0 0 0 2 2h1v-6H5a2 2 0 0 0-2 2v2z" /></g>,
    mic: <g><rect x="9" y="3" width="6" height="11" rx="3" /><path d="M5 11a7 7 0 0 0 14 0M12 18v3" /></g>,
    rss: <g><path d="M4 11a9 9 0 0 1 9 9M4 4a16 16 0 0 1 16 16" /><circle cx="5" cy="19" r="1" fill="currentColor" stroke="none" /></g>,
    spotify: <g><circle cx="12" cy="12" r="9" /><path d="M7.5 10.5c3-1 6-0.7 8.5 0.8M8 13.6c2.4-0.7 4.6-0.4 6.6 0.9M8.5 16.4c1.8-0.5 3.4-0.3 4.9 0.7" /></g>,
    apple: <g><path d="M16 13c0-2 1.5-2.7 1.6-2.8-0.9-1.3-2.3-1.5-2.8-1.5-1.2-0.1-2.3 0.7-2.9 0.7-0.6 0-1.5-0.7-2.5-0.7-1.3 0-2.5 0.8-3.1 2-1.3 2.3-0.3 5.8 0.9 7.7 0.6 0.9 1.4 2 2.4 1.9 1-0.04 1.3-0.6 2.5-0.6 1.2 0 1.5 0.6 2.5 0.6 1 0 1.7-0.9 2.3-1.9 0.4-0.6 0.6-1.2 0.8-1.6-2-0.8-2.2-3.1-2.2-3.2z" /><path d="M14 6.5c0.5-0.7 0.9-1.6 0.8-2.5-0.8 0-1.7 0.5-2.2 1.2-0.5 0.6-0.9 1.5-0.8 2.4 0.9 0.1 1.7-0.4 2.2-1.1z" /></g>,
    google: <g><circle cx="12" cy="12" r="9" /><path d="M12 7v10M8.5 9v6M15.5 9v6" /></g>,
    award: <g><circle cx="12" cy="9" r="5" /><path d="M9 13l-2 8 5-3 5 3-2-8" /></g>,
    clock: <g><circle cx="12" cy="12" r="9" /><path d="M12 7v5l3 2" /></g>,
    calendar: <g><rect x="4" y="5" width="16" height="16" rx="2" /><path d="M4 9h16M9 3v4M15 3v4" /></g>,
    sparkle: <path d="M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8L12 3z" />,
  }[name] || null;
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor"
      strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">{p}</svg>
  );
}

/* ---------- GLOBAL AUDIO PLAYER (single <audio>, one track at a time) ----------
   Remembers the last episode + position in localStorage, so a refresh resumes
   where you left off (position restored on next play of that episode). */
const Player = (function () {
  const audio = typeof Audio !== "undefined" ? new Audio() : {};
  audio.preload = "metadata";
  let saved = {};
  try { saved = JSON.parse(localStorage.getItem("fp-player") || "{}"); } catch (e) {}
  let resumeId = saved.id || null;
  let resumeTime = saved.time || 0;
  let seekTo = 0;
  let lastSave = 0;
  let state = { id: null, playing: false, time: 0, duration: 0, loading: false };
  const subs = new Set();
  const emit = () => { for (const f of subs) f(); };
  const set = (patch) => { state = Object.assign({}, state, patch); emit(); };
  const persist = () => {
    try { localStorage.setItem("fp-player", JSON.stringify({ id: state.id, time: audio.currentTime || 0 })); } catch (e) {}
  };

  if (audio.addEventListener) {
    audio.addEventListener("timeupdate", () => {
      set({ time: audio.currentTime });
      const now = Date.now();
      if (now - lastSave > 2000) { lastSave = now; persist(); }
    });
    audio.addEventListener("durationchange", () => set({ duration: audio.duration || 0 }));
    audio.addEventListener("loadedmetadata", () => {
      if (seekTo > 0) { try { audio.currentTime = seekTo; } catch (e) {} seekTo = 0; }
      set({ duration: audio.duration || 0, loading: false });
    });
    audio.addEventListener("playing", () => set({ playing: true, loading: false }));
    audio.addEventListener("waiting", () => set({ loading: true }));
    audio.addEventListener("play", () => set({ playing: true }));
    audio.addEventListener("pause", () => { set({ playing: false }); persist(); });
    audio.addEventListener("ended", () => { set({ playing: false, time: 0 }); persist(); });
  }

  function play(ep) {
    set({ id: ep.id, time: 0, duration: 0, loading: true });
    seekTo = (ep.id === resumeId && resumeTime > 1) ? resumeTime : 0;
    resumeId = null; // resume only once per load
    audio.src = ep.audio;
    audio.play().catch(() => set({ loading: false, playing: false }));
  }
  function toggle(ep) {
    if (state.id === ep.id) {
      if (audio.paused) audio.play(); else audio.pause();
    } else {
      play(ep);
    }
  }
  function seekFraction(f) {
    if (state.duration) { audio.currentTime = Math.max(0, Math.min(1, f)) * state.duration; persist(); }
  }
  return {
    subscribe(f) { subs.add(f); return () => subs.delete(f); },
    getState() { return state; },
    toggle, play, seekFraction,
  };
})();
window.Player = Player;

function usePlayer() {
  return React.useSyncExternalStore(Player.subscribe, Player.getState);
}

function fmtTime(s) {
  if (!s || !isFinite(s)) return "0:00";
  const m = Math.floor(s / 60), sec = Math.floor(s % 60);
  return m + ":" + String(sec).padStart(2, "0");
}

/* ---------- SHARED COMPONENTS ---------- */

function PlayButton({ ep, size, onDark }) {
  const st = usePlayer();
  const isCur = st.id === ep.id;
  const isPlaying = isCur && st.playing;
  const cls = "pp-play" + (isCur ? " is-active" : "") + (size === "lg" ? " pp-play--lg" : size === "sm" ? " pp-play--sm" : "");
  return (
    <button className={cls} onClick={() => Player.toggle(ep)}
      aria-label={isPlaying ? "Pauzeer" : "Speel af"}>
      {isPlaying
        ? <span className="pp-eq"><span></span><span></span><span></span><span></span></span>
        : <Ic name={isCur ? "pause" : "play"} />}
    </button>
  );
}

function Scrubber({ ep, onDark }) {
  const st = usePlayer();
  const isCur = st.id === ep.id;
  const dur = isCur ? st.duration : 0;
  const cur = isCur ? st.time : 0;
  const frac = dur ? cur / dur : 0;
  const trackRef = React.useRef(null);
  const onSeek = (e) => {
    if (!isCur) return;
    const r = trackRef.current.getBoundingClientRect();
    Player.seekFraction((e.clientX - r.left) / r.width);
  };
  return (
    <div className="pp-scrub">
      <span className="pp-scrub-time">{fmtTime(cur)}</span>
      <div ref={trackRef} className={"pp-track" + (onDark ? " pp-track--ondark" : "")} onClick={onSeek}>
        <div className="pp-track-fill" style={{ width: (frac * 100) + "%" }}></div>
      </div>
      <span className="pp-scrub-time pp-scrub-time--end">
        {isCur && dur ? "-" + fmtTime(dur - cur) : ep.dur.replace(" min", ":00")}
      </span>
    </div>
  );
}

function Monogram({ initials }) {
  return <div className="pp-mono">{initials}</div>;
}

/* ---------- NAV ---------- */
function Nav({ theme }) {
  const links = ["Afleveringen", "Over", "Hosts", "Abonneer"];
  return (
    <div className={"pp-nav " + (theme === "dark" ? "pp-nav--on-dark" : "pp-nav--on-light")}>
      <div className="pp-brand">
        <img src="assets/vector-mark.png" alt="Vector" />
        <span className="pp-brand-word">VECTOR</span>
        <span className="pp-brand-div"></span>
        <span className="pp-brand-show">Financieel Perspectief</span>
      </div>
      <nav className="pp-nav-links">
        {links.map((l) => <a key={l}>{l}</a>)}
      </nav>
      <div className="pp-nav-right">
        <span className="pp-lang"><b>NL</b><i></i>EN<i></i>FR</span>
        <button className={"pp-btn pp-btn--sm " + (theme === "dark" ? "pp-btn--ghost" : "pp-btn--navy")}
          style={{ padding: "10px 18px", fontSize: "14px" }}>
          <Ic name="headphones" size={16} /> Abonneer
        </button>
      </div>
    </div>
  );
}

/* ---------- HOST CARDS ---------- */
function HostGrid({ variant }) {
  const cardCls = variant === "c" ? "vc-host-card" : "pp-host-card";
  return (
    <div className="pp-hosts">
      {window.POD.HOSTS.map((h) => (
        <div key={h.name} className={cardCls}>
          <Monogram initials={h.initials} />
          <div>
            <div className="pp-host-name">{h.name}</div>
            <div className="pp-host-role">{h.role}</div>
            <p className="pp-host-bio">{h.bio}</p>
          </div>
        </div>
      ))}
    </div>
  );
}

/* ---------- FOOTER ---------- */
function Footer() {
  const plats = [
    { name: "Spotify", icon: "spotify" },
    { name: "Apple Podcasts", icon: "apple" },
    { name: "Google Podcasts", icon: "google" },
    { name: "RSS", icon: "rss" },
  ];
  return (
    <div className="pp-foot">
      <div className="pp-foot-glow"></div>
      <div className="pp-foot-inner">
        <div className="pp-foot-top">
          <div className="pp-foot-sub">
            <div className="pp-brand">
              <img src="assets/vector-mark.png" alt="Vector" style={{ height: 30 }} />
              <span className="pp-brand-word" style={{ color: "#fff" }}>VECTOR</span>
            </div>
            <p>Financieel Perspectief is de podcast van Vector Asset Management S.A. — over investeren, vermogen en het geduld dat beide vragen.</p>
            <div className="pp-subscribe">
              {plats.map((p) => (
                <span key={p.name} className="pp-plat"><Ic name={p.icon} size={16} /> {p.name}</span>
              ))}
            </div>
          </div>
          <div style={{ textAlign: "right" }}>
            <div className="pp-eyebrow pp-eyebrow--mute" style={{ marginBottom: 10 }}>Vector Asset Management S.A.</div>
            <div style={{ fontFamily: "var(--font-body)", fontSize: "14px", lineHeight: 1.7, color: "var(--fg-on-dark-2)" }}>
              370, Route de Longwy<br />L-1940 Luxembourg<br />
              <span style={{ fontFamily: "var(--font-mono)" }}>+352 26 97 64 27</span>
            </div>
          </div>
        </div>
        <p className="pp-foot-disc">
          In afleveringen wordt algemene informatie gedeeld; niets vormt beleggingsadvies. In het verleden behaalde resultaten
          bieden geen garantie voor de toekomst. De waarde van beleggingen kan zowel stijgen als dalen.
        </p>
        <div className="pp-foot-legal">
          <span>© 2026 Vector Asset Management S.A.</span>
          <span style={{ display: "flex", gap: 18 }}>
            <span>Disclaimer</span><span>Privacy</span><span>Contact</span>
          </span>
        </div>
      </div>
    </div>
  );
}

/* ---------- SECTION HEADER ---------- */
function SectionHead({ eyebrow, title, lead, align }) {
  return (
    <div className="pp-section-head" style={align === "center" ? { margin: "0 auto", textAlign: "center" } : null}>
      <p className="pp-eyebrow">{eyebrow}</p>
      <h2 className="pp-h2" style={{ marginTop: 12 }}>{title}</h2>
      {lead ? <p className="pp-lead">{lead}</p> : null}
    </div>
  );
}

Object.assign(window, {
  Ic, usePlayer, fmtTime, PlayButton, Scrubber, Monogram, Nav, HostGrid, Footer, SectionHead,
});
