// /v6/js/script.js
// Player v6 — stable, sans flash blanc, aucun changement de structure
(function () {
  "use strict";

  /* ---------------------- helpers ---------------------- */
  const $  = (s, r=document) => r.querySelector(s);
  const $$ = (s, r=document) => Array.from(r.querySelectorAll(s));
  const json = (url) => fetch(url, { cache: "no-store" }).then(r => {
    if (!r.ok) throw Error(r.status);
    return r.json();
  });

  const els = {
    // Now Playing
    song:        $("#currentSong"),
    artist:      $("#currentArtist"),
    artBox:      $("#currentCoverArt"),
    bgCover:     $("#bgCover"),

    // Controls
    playBtn:     $("#btnPlay"),
    playIcon:    $("#playerButton"),
    vol:         $("#volume"),
    volIndicator:$("#volIndicator"),

    // History (colonne gauche)
    histList:    $("#historyPanelList"),

    // Share & Lyrics
    shareBtn:    $("#btnShare"),
    lyrModalBody:$("#lyric"),
    lyricsTrigger: $('[data-target="#modalLyrics"]'),
    lyricsTitle: $("#lyricsSong"),

    // Clock
    clockTime:   $("#clockTime"),
    clockDate:   $("#clockDate"),

    // Footer year
    yearNow:     $("#yearNow"),

    // Popups
    lnkAbout:    $("#lnkAbout"),
    lnkTerms:    $("#lnkTerms"),
    lnkPrivacy:  $("#lnkPrivacy"),
    aboutBody:   $("#aboutBody"),
    termsBody:   $("#termsBody"),
    privacyBody: $("#privacyBody"),

    // Stores (gauche)
    storesLeftHolder: $("#storesLeftHolder"),
    storeGoogle:      $("#storeGoogle"),
    storeApple:       $("#storeApple"),

    // Socials (droite)
    socWhatsApp:  $("#socWhatsApp"),
    socFacebook:  $("#socFacebook"),
    socInstagram: $("#socInstagram"),
    socTikTok:    $("#socTikTok"),
    socYouTube:   $("#socYouTube"),

    // Theme toggle
    themeToggle:  $("#themeToggle"),
    themeIcon:    $("#themeIcon"),

    // Titre widget paroles (droite)
    rightLyricsWidgetTitle: document.querySelector('.card-title[data-lyrics-title]'),
  };

  let CFG = null;
  let audio = null;
  let lastMetaKey = "";
  let retryCount = 0;

  /* ---------------------- UI helpers ---------------------- */
  const setText = (el, txt) => { if (el) el.textContent = txt || ""; };

  function cfg(path, def) {
    try { return path.split(".").reduce((o, k) => (o && k in o) ? o[k] : undefined, CFG) ?? def; }
    catch(_) { return def; }
  }

  function softNote(msg, ms=1800) {
    let box = $("#gsa-note");
    if (!box) {
      box = document.createElement("div");
      box.id = "gsa-note";
      box.style.cssText =
        "position:fixed;left:16px;bottom:72px;z-index:9999;padding:10px 12px;border-radius:10px;" +
        "background:rgba(0,0,0,.75);color:#fff;font:500 13px/1.25 Poppins,system-ui;" +
        "box-shadow:0 8px 18px rgba(0,0,0,.25);transition:opacity .2s";
      document.body.appendChild(box);
    }
    box.textContent = msg;
    box.style.opacity = "1";
    clearTimeout(box._t);
    box._t = setTimeout(() => { box.style.opacity = "0"; }, ms);
  }

  /* ---------------------- Artwork : anti-flash ---------------------- */
  function setCover(url) {
    if (!els.artBox) return;
    const holder = els.artBox;

    holder.classList.add("loading-artwork-main");
    holder.classList.remove("ready");

    const img = new Image();
    img.alt = "Pochette";
    img.decoding = "async";
    img.loading = "eager";

    img.onload = () => {
      holder.innerHTML = "";
      holder.appendChild(img);
      holder.classList.remove("loading-artwork-main");
      holder.classList.add("ready");
      if (els.bgCover) els.bgCover.style.backgroundImage = `url("${url}")`;
    };

    img.onerror = () => {
      holder.classList.remove("loading-artwork-main");
      holder.classList.remove("ready");
    };

    img.src = url;
  }

  /* ---------------------- History ---------------------- */
  const fmtTime = (ts) => {
    if (!ts) return "";
    try { return new Date(ts * 1000).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }); }
    catch(_) { return ""; }
  };

  function renderHistory(items) {
    const target = els.histList; if (!target) return;

    const list = items || [];
    if (!list.length) {
      target.innerHTML = `<div class="history-empty" style="opacity:.7;padding:8px 0">Aucun historique.</div>`;
      return;
    }
    const fallbackCover = cfg("default_cover", "/v6/img/cover.jpg");

    target.innerHTML = list.map(it => `
      <article class="history-row">
        <div class="h-cover"><img src="${(it.artwork || fallbackCover)}" alt=""></div>
        <div class="h-meta">
          <h4 class="h-title">${(it.song || "").replace(/</g,"&lt;")}</h4>
          <p class="h-artist">${(it.artist || "").replace(/</g,"&lt;")}</p>
          ${it.time ? `<time class="h-time">${fmtTime(it.time)}</time>` : ``}
        </div>
      </article>
    `).join("");
  }

  /* ---------------------- Audio ---------------------- */
  function updatePlayIcon(state){
    if (!els.playIcon) return;
    els.playIcon.className = (state === "playing") ? "fa fa-pause" : "fa fa-play";
  }

  function ensureAudio() {
    if (audio) return;
    const u = cfg("stream_url", "");
    if (!u) return;

    audio = new Audio();
    audio.src = u;
    audio.preload = "none";
    audio.crossOrigin = "anonymous";
    audio.playsInline = true;
    audio.type = "audio/mpeg";

    audio.addEventListener("play",    () => { retryCount = 0; updatePlayIcon("playing"); });
    audio.addEventListener("playing", () => { retryCount = 0; updatePlayIcon("playing"); });
    audio.addEventListener("pause",   () => { updatePlayIcon("paused"); });
    audio.addEventListener("ended",   () => { updatePlayIcon("paused"); });

    audio.addEventListener("error",   () => retryPlay("Réessai du flux…"));
    audio.addEventListener("stalled", () => retryPlay("Flux en attente…"));
    audio.addEventListener("abort",   () => retryPlay("Connexion interrompue. Nouvelle tentative…"));

    const initV = parseInt(els.vol?.value || "80", 10);
    if (els.vol) {
      audio.volume = Math.max(0, Math.min(1, initV / 100));
      if (els.volIndicator) els.volIndicator.textContent = initV;
      document.documentElement.style.setProperty("--vol", initV + "%");

      els.vol.addEventListener("input", () => {
        if (!audio) return;
        const v = parseInt(els.vol.value || "80", 10);
        audio.volume = Math.max(0, Math.min(1, v / 100));
        if (els.volIndicator) els.volIndicator.textContent = v;
        document.documentElement.style.setProperty("--vol", v + "%");
      });
    }

    if (els.playBtn && !els.playBtn.getAttribute("onclick") && !els.playBtn._binded) {
      els.playBtn.addEventListener("click", togglePlay);
      els.playBtn._binded = true;
    }
  }

  function retryPlay(msg){
    softNote(msg);
    if (!audio) return;
    if (retryCount >= 3) return;
    retryCount++;
    setTimeout(() => { if (audio.paused) tryPlay().catch(()=>{}); }, 800 * retryCount);
  }

  async function tryPlay(){
    ensureAudio();
    if (!audio) { softNote("Flux non configuré."); return; }
    if (audio.readyState === 0) audio.load();
    return audio.play();
  }

  async function togglePlay(){
    try{
      ensureAudio();
      if(!audio){ softNote("Flux non configuré."); return; }
      if (audio.paused){
        await tryPlay();
        updatePlayIcon("playing");
        softNote("Lecture…", 1200);
      } else {
        audio.pause();
        updatePlayIcon("paused");
      }
    }catch(_){
      updatePlayIcon("paused");
      retryPlay("Impossible de démarrer le flux. Nouvelle tentative…");
    }
  }
  window.togglePlay = togglePlay;

  /* ---------------------- Share / Lyrics ---------------------- */

  // Base64URL (pour cacher l'URL de la pochette dans le lien)
  function b64u(str){
    return btoa(unescape(encodeURIComponent(str)))
      .replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,'');
  }

  // Image proxifiée SANS exposer le domaine source (FogID.php)
  function proxiedImageUrl(rawUrl){
    const isLocal = !rawUrl || rawUrl.startsWith(location.origin) || rawUrl.startsWith("/");
    if (isLocal) return rawUrl || cfg("default_cover","/v6/img/cover.jpg");
    const id = b64u(rawUrl);
    return `/v6/FogID.php?id=${id}&w=500&h=500&fit=cover`;
  }

  // URL de partage avec métadonnées — mobile + desktop
  function richShareUrl({ title, artist, artwork }) {
    const base = `${location.origin}/v6/share.php`;
    const img  = artwork || "/v6/img/cover.jpg";

    const _b64u = (s) => {
      const b = btoa(unescape(encodeURIComponent(s)));
      return b.replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,'');
    };

    let u = `${location.origin}/v6/`;
    if (!u.endsWith("/")) u += "/";

    const q = new URLSearchParams({
      title:  title  || "",
      artist: artist || "",
      i:      _b64u(img),
      u
    });
    return `${base}?${q.toString()}`;
  }

  function doShare(artist, song, artwork){
    const title = (song && artist) ? `${song} — ${artist}` : (song || "Écouter la radio");
    const text  = "Écoute le direct sur Global Streaming Africa.";
    const shareUrl = richShareUrl({ title: song || "", artist: artist || "", artwork });

    if (navigator.share) {
      navigator.share({ title, text, url: shareUrl }).catch(()=>{});
    } else {
      const toCopy = `${title}\n${shareUrl}`;
      if (navigator.clipboard?.writeText) {
        navigator.clipboard.writeText(toCopy).then(()=>softNote("Lien copié.")).catch(()=>softNote(shareUrl));
      } else {
        softNote(shareUrl);
      }
    }
  }

  // --- FONCTIONS LYRICS (fallback propre) ---
  function tidy(s){ return (s||"").toString().trim(); }

  // Remplacement — fallback propre "Paroles indisponibles." + timeout
  async function openLyrics(artist, song){
    if (!els.lyrModalBody) return;

    // état "chargement"
    els.lyrModalBody.innerHTML =
      `<div class="lyrics-loading">
         <div class="lyrics-skeleton-line"></div>
         <div class="lyrics-skeleton-line"></div>
         <div class="lyrics-skeleton-line short"></div>
       </div>`;

    // si meta absente => fallback direct
    if (!artist || !song){
      els.lyrModalBody.innerHTML = `<div class="lyrics-empty">Paroles indisponibles.</div>`;
      return;
    }

    const url = `/v6/api/lyrics.php?artist=${encodeURIComponent(artist)}&title=${encodeURIComponent(song)}&cb=${Date.now()}`;

    // petit helper pour échapper le HTML
    const esc = (s)=> s.replace(/[<>&]/g, m => ({'<':'&lt;','>':'&gt;','&':'&amp;'}[m]));

    // timeout doux pour ne pas bloquer l'UI
    const ctrl = new AbortController();
    const timer = setTimeout(()=>ctrl.abort(), 7000);

    try{
      const r = await fetch(url, { cache:'no-store', signal: ctrl.signal });
      const j = await r.json().catch(()=>null);

      const L = j && j.ok && j.lyrics ? String(j.lyrics).trim() : "";
      els.lyrModalBody.innerHTML = L
        ? `<pre class="lyrics-pre">${esc(L)}</pre>`
        : `<div class="lyrics-empty">Paroles indisponibles.</div>`;
    }catch(_){
      // réseau / timeout / 404
      els.lyrModalBody.innerHTML = `<div class="lyrics-empty">Paroles indisponibles.</div>`;
    }finally{
      clearTimeout(timer);
    }
  }

  /* ---------------------- Data refresh ---------------------- */
  async function refresh() {
    try{
      const d = await json("/v6/api/adapter.php?cb=" + Date.now());
      const artist  = d.artist || "";
      const song    = d.song   || "";
      const artwork = d.artwork || cfg("default_cover", "/v6/img/cover.jpg");

      const metaKey = artist + " - " + song;
      if (metaKey !== lastMetaKey) {
        setText(els.song,   song   || "—");
        setText(els.artist, artist || "");
        setCover(artwork);
        lastMetaKey = metaKey;

        // Hook public non bloquant (utile si on ajoute un module plus tard)
        window.dispatchEvent(new CustomEvent("np:track", { detail: { artist, title: song } }));
      }

      renderHistory(d.history || []);

      if (els.shareBtn) {
        els.shareBtn.onclick = () => doShare(artist, song, artwork);
      }

      if (els.lyricsTrigger && !els._lyricsBound) {
        els.lyricsTrigger.addEventListener("click", () => {
          const a = els.artist?.textContent.trim() || "";
          const s = els.song?.textContent.trim() || "";
          els.lyricsTitle && (els.lyricsTitle.textContent = (s && a) ? `${s} — ${a}` : "Lyrics");
          openLyrics(a, s);
        });
        els._lyricsBound = true;
      }
    }catch(_){ /* silencieux */ }
  }

  /* ---------------------- Clock ---------------------- */
  function tickClock(){
    if (!els.clockTime || !els.clockDate) return;
    const d = new Date();
    els.clockTime.textContent = d.toLocaleTimeString("fr-FR", { hour:"2-digit", minute:"2-digit", second:"2-digit" });
    els.clockDate.textContent = `Aujourd’hui · ${d.toLocaleDateString("fr-FR", { weekday:"long", day:"numeric", month:"long", year:"numeric" })}`;
  }

  /* ---------------------- Theme ---------------------- */
  function applyTheme(theme){
    const isDark = theme === "dark";
    document.body.classList.toggle("theme-dark",  isDark);
    document.body.classList.toggle("theme-light", !isDark);
    if (els.themeIcon) els.themeIcon.className = isDark ? "fa fa-sun-o" : "fa fa-moon-o";
    document.body.style.setProperty("--art-bg", isDark ? "rgba(0,0,0,.25)" : "rgba(0,0,0,.06)");
  }

  function initTheme(){
    let t = localStorage.getItem("gsa_theme");
    if (!t) {
      const cfgText = (cfg("theme.text","dark") || "").toLowerCase();
      t = (cfgText === "light" || cfgText === "clair") ? "light" : "dark";
      localStorage.setItem("gsa_theme", t);
    }
    applyTheme(t);

    if (els.themeToggle && !els.themeToggle._bound) {
      els.themeToggle.addEventListener("click", () => {
        const cur  = localStorage.getItem("gsa_theme") || "dark";
        const next = cur === "dark" ? "light" : "dark";
        localStorage.setItem("gsa_theme", next);
        applyTheme(next);
      });
      els.themeToggle._bound = true;
    }
  }

  /* ---------------------- Stores / Socials ---------------------- */
  function setLink(anchorImg, url){
    if (!anchorImg) return;
    const a = anchorImg.closest("a") || anchorImg.parentElement;
    if (!a) return;
    if (url) { a.href = url; a.style.display = ""; }
    else     { a.style.display = "none"; }
  }

  function initStoresAndSocials() {
    setLink(els.storeGoogle, cfg("play_store_url", ""));
    setLink(els.storeApple,  cfg("app_store_url",  ""));

    const S = cfg("socials", {}) || {};
    const map = {
      socWhatsApp:  S.whatsapp,
      socFacebook:  S.facebook,
      socInstagram: S.instagram,
      socTikTok:    S.tiktok,
      socYouTube:   S.youtube
    };
    Object.entries(map).forEach(([id, url]) => {
      const a = els[id];
      if (!a) return;
      if (url) { a.href = url; a.style.display = ""; }
      else     { a.style.display = "none"; }
    });
  }

  /* ---------------------- Popups ---------------------- */
  async function fetchInto(el, url){
    if (!el || !url) return;
    try { const r = await fetch(url, { cache:"no-store" }); el.innerHTML = await r.text(); }
    catch(_) { el.innerHTML = `<div style="opacity:.8">Contenu indisponible.</div>`; }
  }

  function initPopups(){
    const URLS = {
      about:   "/v6/data/a-propos.html",
      terms:   cfg("legal.terms_popup",   "/v6/data/terms.html"),
      privacy: cfg("legal.privacy_popup", "/v6/data/privacy.html")
    };
    els.lnkAbout?.addEventListener("click",  () => fetchInto(els.aboutBody,  URLS.about));
    els.lnkTerms?.addEventListener("click",  () => fetchInto(els.termsBody,  URLS.terms));
    els.lnkPrivacy?.addEventListener("click",() => fetchInto(els.privacyBody,URLS.privacy));
  }

  /* ---------------------- Init ---------------------- */
  document.addEventListener("DOMContentLoaded", async () => {
    els.rightLyricsWidgetTitle && (els.rightLyricsWidgetTitle.textContent = "Paroles du titre en cours");
    els.yearNow && (els.yearNow.textContent = new Date().getFullYear());

    try {
      CFG = await json("/v6/data/config.json?cb=" + Date.now());
    } catch(_){
      CFG = { default_cover: "/v6/img/cover.jpg" };
      console.warn("Impossible de charger /v6/data/config.json");
    }

    // Theme d'abord
    initTheme();

    // Audio & refresh
    ensureAudio();
    refresh(); setInterval(refresh, 8000);

    // Clock
    tickClock(); setInterval(tickClock, 1000);

    // Stores/Socials
    initStoresAndSocials();

    // Popups
    initPopups();

    // Icône cohérente au démarrage
    updatePlayIcon((audio && !audio.paused) ? "playing" : "paused");
  });
})();
