// VIEWER — full-bleed broadcast view, syncs with the active playlist
const { useState: vUseState, useEffect: vUseEffect } = React;

const VIEWER_LAYOUTS = {
  full:      { grid: "1fr / 1fr", zones: ["A"] },
  "split-h": { grid: "1fr / 1fr 1fr", zones: ["A", "B"] },
  "split-v": { grid: "1fr 1fr / 1fr", zones: ["A", "B"] },
  "main-side": { grid: "1fr 1fr / 2fr 1fr", zones: ["A", "B", "C"], spans: { A: "1 / 1 / 3 / 2" } },
  quad:      { grid: "1fr 1fr / 1fr 1fr", zones: ["A", "B", "C", "D"] },
  main3:     { grid: "2fr 1fr 1fr / 2fr 1fr", zones: ["A", "B", "C", "D"], spans: { A: "1 / 1 / 3 / 2", B: "1 / 2 / 2 / 3", C: "2 / 2 / 3 / 3", D: "3 / 1 / 4 / 3" } },
};

function ViewerClock() {
  const [now, setNow] = vUseState(new Date());
  vUseEffect(() => {
    const id = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const time = now.toLocaleTimeString("fr-FR", { hour: "2-digit", minute: "2-digit" });
  const seconds = now.toLocaleTimeString("fr-FR", { second: "2-digit" });
  const date = now.toLocaleDateString("fr-FR", { weekday: "long", day: "numeric", month: "long" });
  return (
    <div className="viewer-clock">
      <div className="viewer-clock__time">
        {time}<span className="viewer-clock__seconds">:{seconds}</span>
      </div>
      <div className="viewer-clock__date">{date}</div>
    </div>
  );
}

// ============================================================
// Tile renderers per item type
// ============================================================

function ZoneCorner({ zone, label, idx, total }) {
  return (
    <div className="vz__corner">
      <span className="vz__corner-letter">{zone}</span>
      <span className="vz__corner-label">
        {label}{total > 1 ? ` · ${idx + 1}/${total}` : ""}
      </span>
    </div>
  );
}

// Slide tile (pdf, ppt)
// Slideshow PDF : récupère la liste des pages PNG depuis le serveur et les cycle
function PdfSlideshow({ item, label, ...corner }) {
  const [pages, setPages] = vUseState([]);
  const [idx, setIdx] = vUseState(0);
  const [error, setError] = vUseState(null);

  vUseEffect(() => {
    let cancelled = false;
    fetch(`/api/media/${item.mediaId}/pages`)
      .then(r => r.ok ? r.json() : Promise.reject(r.status))
      .then(d => { if (!cancelled) setPages(d.pages || []); })
      .catch(e => { if (!cancelled) setError(String(e)); });
    return () => { cancelled = true; };
  }, [item.mediaId]);

  vUseEffect(() => {
    if (pages.length < 2) return;
    const id = setInterval(() => setIdx(i => (i + 1) % pages.length), 6000);
    return () => clearInterval(id);
  }, [pages]);

  if (error) {
    return (
      <div className="vz vz--real-media" style={{ display: "flex", alignItems: "center", justifyContent: "center", color: "#f87171", fontSize: 14 }}>
        <ZoneCorner label={label} {...corner} />
        Erreur de rendu PDF : {error}
      </div>
    );
  }
  if (pages.length === 0) {
    return (
      <div className="vz vz--real-media" style={{ display: "flex", alignItems: "center", justifyContent: "center", color: "#9CA3AF", fontSize: 13 }}>
        <ZoneCorner label={label} {...corner} />
        Chargement du PDF…
      </div>
    );
  }
  return (
    <div className="vz vz--real-media vz--pdf-slideshow">
      <ZoneCorner label={label} {...corner} />
      {pages.map((src, i) => (
        <img
          key={src}
          src={src}
          alt={`Page ${i + 1}`}
          className={"vz-pdf__page" + (i === idx ? " vz-pdf__page--active" : "")}
          loading={i === 0 ? "eager" : "lazy"}
        />
      ))}
      <div className="vz-pdf__pager">
        {item.title.replace(/\.pdf$/i, "")} · page {idx + 1}/{pages.length}
      </div>
    </div>
  );
}

// Rendu réel d'un fichier uploadé (image, video, office)
function RealMediaTile({ item, label, ...corner }) {
  const url = `/api/media/${item.mediaId}/file`;
  const absUrl = window.location.origin + url;
  // Office Online Viewer pour pptx/xlsx/docx
  const officeViewer = `https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(absUrl)}&wdHideHeaders=true&wdHideGridlines=true`;

  if (item.type === "img") {
    return (
      <div className="vz vz--real-media">
        <ZoneCorner label={label || "PHOTO"} {...corner} />
        <img src={url} alt={item.title} className="vz-real__img" />
        <div className="vz-real__caption">
          <div className="vz-real__title">{item.title.replace(/\.(jpg|jpeg|png|gif|webp|svg)$/i, "")}</div>
        </div>
      </div>
    );
  }

  if (item.type === "vid") {
    return (
      <div className="vz vz--real-media">
        <ZoneCorner label={label || "VIDÉO"} {...corner} />
        <video src={url} className="vz-real__video" autoPlay muted loop playsInline />
      </div>
    );
  }

  if (item.type === "pdf") {
    return <PdfSlideshow item={item} label={label || "DOCUMENT"} {...corner} />;
  }

  if (item.type === "ppt" || item.type === "xls" || item.type === "doc") {
    return (
      <div className="vz vz--real-media">
        <ZoneCorner label={label || (item.type === "ppt" ? "PRÉSENTATION" : item.type === "xls" ? "TABLEAU" : "DOCUMENT")} {...corner} />
        <iframe
          src={officeViewer}
          className="vz-real__iframe"
          title={item.title}
          allow="fullscreen"
        />
      </div>
    );
  }

  return null;
}

function SlideTile({ item, ...corner }) {
  return (
    <div className="vz vz--slide">
      <ZoneCorner label={item.type === "pdf" ? "DOCUMENT" : "PRÉSENTATION"} {...corner} />
      <div className="vz-slide__inner">
        <div className="vz-slide__meta">{item.duration} de lecture</div>
        <h2 className="vz-slide__title">{item.title.replace(/\.(pdf|pptx|key)$/i, "")}</h2>
        <div className="vz-slide__sub">
          {item.type === "pdf" ? "Document partagé · Lecture automatique" : "Présentation · Lecture automatique"}
        </div>
        <div className="vz-slide__stats">
          <div className="vz-slide__stat">
            <div className="vz-slide__stat-num">38<small>ha</small></div>
            <div className="vz-slide__stat-lbl">Surface</div>
          </div>
          <div className="vz-slide__stat">
            <div className="vz-slide__stat-num">1 200</div>
            <div className="vz-slide__stat-lbl">Logements</div>
          </div>
          <div className="vz-slide__stat">
            <div className="vz-slide__stat-num">2027</div>
            <div className="vz-slide__stat-lbl">Livraison</div>
          </div>
          <div className="vz-slide__stat">
            <div className="vz-slide__stat-num">42<small>%</small></div>
            <div className="vz-slide__stat-lbl">Espaces verts</div>
          </div>
        </div>
      </div>
      <div className="vz-slide__progress">
        <div className="vz-slide__progress-bar"><div /></div>
      </div>
    </div>
  );
}

// KPI tile
function KpiTile({ item, ...corner }) {
  // Pick a number based on title content to simulate a real KPI
  const isAccident = /accident|s\u00e9curit\u00e9|qse/i.test(item.title);
  const num = isAccident ? "247" : Math.floor(80 + Math.random() * 200).toString();
  return (
    <div className="vz vz--kpi">
      <ZoneCorner label="KPI · TEMPS RÉEL" {...corner} />
      <div className="vz-kpi__inner">
        <div className="vz-kpi__label">{item.title.toUpperCase()}</div>
        <div className="vz-kpi__num">{num}</div>
        <div className="vz-kpi__trend">
          <strong>↑ +12</strong> vs mois dernier
        </div>
        <div className="vz-kpi__record">Source · Direction QSE</div>
      </div>
    </div>
  );
}

// Data table tile (xls)
function DataTile({ item, ...corner }) {
  return (
    <div className="vz vz--data">
      <ZoneCorner label="DONNÉES" {...corner} />
      <div className="vz-data__inner">
        <div className="vz-data__meta">{item.duration} · {item.title}</div>
        <div className="vz-data__title">Tableau de bord</div>
        <div className="vz-data__grid">
          {Array.from({ length: 4 }).map((_, i) => (
            <div key={i} className="vz-data__cell">
              <div className="vz-data__cell-num">{[247, 12.4, 98, 1284][i]}{["", " M€", " %", ""][i]}</div>
              <div className="vz-data__cell-lbl">{["Indicateur " + (i+1), "Volume", "Conformité", "Total"][i]}</div>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

// Photo tile
function PhotoTile({ item, ...corner }) {
  return (
    <div className="vz vz--photo">
      <ZoneCorner label="PHOTO" {...corner} />
      <div className="vz-photo__bg">
        <svg viewBox="0 0 800 450" preserveAspectRatio="xMidYMid slice" style={{ width: "100%", height: "100%", position: "absolute", inset: 0 }}>
          <defs>
            <linearGradient id="ph-sky" x1="0" x2="0" y1="0" y2="1">
              <stop offset="0%" stopColor="#2A3142" />
              <stop offset="60%" stopColor="#181D2A" />
              <stop offset="100%" stopColor="#0A0E17" />
            </linearGradient>
          </defs>
          <rect width="800" height="450" fill="url(#ph-sky)" />
          <g fill="#0A0E17" opacity="0.85">
            <rect x="0" y="280" width="160" height="170" />
            <rect x="160" y="240" width="80" height="210" />
            <rect x="240" y="300" width="120" height="150" />
            <rect x="560" y="260" width="100" height="190" />
            <rect x="660" y="290" width="80" height="160" />
            <rect x="740" y="310" width="60" height="140" />
          </g>
          <g stroke="#050810" strokeWidth="3" fill="none" opacity="0.9">
            <line x1="420" y1="450" x2="420" y2="160" />
            <line x1="420" y1="180" x2="540" y2="180" strokeWidth="4" />
            <line x1="420" y1="180" x2="340" y2="180" strokeWidth="3" />
          </g>
          <circle cx="560" cy="140" r="100" fill="#F5B842" opacity="0.04" />
        </svg>
      </div>
      <div className="vz-photo__caption">
        <div className="vz-photo__cap-title">{item.title.replace(/\.(jpg|jpeg|png|gif|webp)$/i, "")}</div>
        <div className="vz-photo__cap-meta">Galerie Elsia · {item.duration}</div>
      </div>
    </div>
  );
}

// Video tile (vid, yt)
function VideoTile({ item, ...corner }) {
  return (
    <div className="vz vz--video">
      <ZoneCorner label={item.type === "yt" ? "YOUTUBE" : "VIDÉO"} {...corner} />
      <div className="vz-video__bg" />
      <div className="vz-video__center">
        <div className="vz-video__play"><Icon.Play size={36} /></div>
        <div className="vz-video__title">{item.title.replace(/\.(mp4|mov|webm)$/i, "")}</div>
        <div className="vz-video__duration">{item.duration}</div>
      </div>
    </div>
  );
}

// Social tile (soc)
function SocialTile({ item, ...corner }) {
  return (
    <div className="vz vz--social">
      <ZoneCorner label="RÉSEAU SOCIAL" {...corner} />
      <div className="vz-social__inner">
        <div className="vz-social__head">
          <div className="vz-social__avatar">
            <div style={{ width: "100%", height: "100%", display: "flex", alignItems: "center", justifyContent: "center", background: "#2A3142", color: "#fff", fontFamily: "var(--font-display)", fontWeight: 600, fontSize: 18 }}>E</div>
          </div>
          <div style={{ flex: 1 }}>
            <div className="vz-social__author">Elsia <span style={{ color: "#60A5FA" }}>✓</span></div>
            <div className="vz-social__sub">Groupe ERI · Façonner la Ville Durable</div>
            <div className="vz-social__time">il y a 2 h · 🌍</div>
          </div>
          <div className="vz-social__icon"><Icon.Linkedin size={20} /></div>
        </div>
        <div className="vz-social__body">
          Nous sommes fiers d'avoir livré ce mois-ci le <strong>Pont d'Aturri</strong> à Bayonne — un ouvrage d'art de 142&nbsp;m qui relie deux quartiers et désenclave la Zone Sud.
          <br/><br/>
          <span style={{ color: "#7DD3FC" }}>#ConstructionDurable #TravauxPublics #Bayonne #Elsia</span>
        </div>
        <div className="vz-social__metrics">
          <span>♥ <strong>184</strong></span>
          <span>💬 <strong>32</strong></span>
          <span>↻ <strong>47</strong></span>
        </div>
      </div>
    </div>
  );
}

// Weather tile (met)
function WeatherTile({ item, ...corner }) {
  return (
    <div className="vz vz--weather">
      <ZoneCorner label="MÉTÉO · TEMPS RÉEL" {...corner} />
      <div className="vz-weather__inner">
        <Icon.Sun size={88} />
        <div className="vz-weather__temp">21<span>°</span></div>
        <div className="vz-weather__city">Bordeaux · Partiellement nuageux</div>
        <div className="vz-weather__forecast">
          <div><div className="vz-weather__day">DEMAIN</div><div className="vz-weather__small-temp">23°</div></div>
          <div><div className="vz-weather__day">MER.</div><div className="vz-weather__small-temp">19°</div></div>
          <div><div className="vz-weather__day">JEU.</div><div className="vz-weather__small-temp">22°</div></div>
          <div><div className="vz-weather__day">VEN.</div><div className="vz-weather__small-temp">24°</div></div>
        </div>
      </div>
    </div>
  );
}

// Text announcement tile (txt)
function TextTile({ item, ...corner }) {
  return (
    <div className="vz vz--text">
      <ZoneCorner label="ANNONCE" {...corner} />
      <div className="vz-text__inner">
        <h2 className="vz-text__title">{item.title}</h2>
        <div className="vz-text__sub">Communication interne · Service RH</div>
      </div>
    </div>
  );
}

// Empty zone
function EmptyTile({ zone, layout }) {
  return (
    <div className="vz vz--empty">
      <div className="vz__corner">
        <span className="vz__corner-letter">{zone}</span>
        <span className="vz__corner-label">ZONE VIDE</span>
      </div>
      <div className="vz-empty__inner">
        <Icon.Playlist size={40} />
        <div className="vz-empty__title">Aucun contenu</div>
        <div className="vz-empty__sub">Ajoutez des tuiles à la zone {zone} depuis le contrôleur.</div>
      </div>
    </div>
  );
}

// Dispatch by type
function ViewerTile({ item, zone, idx, total }) {
  if (!item) return <EmptyTile zone={zone} />;
  const props = { item, zone, idx, total };

  // Si un vrai fichier est uploadé OU si c'est un YouTube avec URL → afficher le vrai contenu
  if (item.has_file && ["img", "vid", "pdf", "ppt", "xls", "doc"].includes(item.type)) {
    return <RealMediaTile {...props} />;
  }
  if (item.type === "yt" && item.external_url) {
    return <YouTubeTile {...props} />;
  }

  // Fallback : placeholders stylisés du proto
  switch (item.type) {
    case "pdf":
    case "ppt": return <SlideTile {...props} />;
    case "kpi": return <KpiTile {...props} />;
    case "xls": return <DataTile {...props} />;
    case "img": return <PhotoTile {...props} />;
    case "vid":
    case "yt": return <VideoTile {...props} />;
    case "soc": return <SocialTile {...props} />;
    case "met": return <WeatherTile {...props} />;
    case "txt":
    default: return <TextTile {...props} />;
  }
}

// Tile YouTube — embed officiel
function YouTubeTile({ item, ...corner }) {
  const m = (item.external_url || "").match(/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([\w-]+)/);
  const videoId = m ? m[1] : null;
  if (!videoId) {
    return (
      <div className="vz vz--video">
        <ZoneCorner label="YOUTUBE" {...corner} />
        <div style={{ padding: 20, color: "#aaa" }}>URL YouTube invalide : {item.external_url}</div>
      </div>
    );
  }
  const embedUrl = `https://www.youtube.com/embed/${videoId}?autoplay=1&mute=1&loop=1&playlist=${videoId}&controls=0&modestbranding=1&rel=0`;
  return (
    <div className="vz vz--real-media">
      <ZoneCorner label="YOUTUBE" {...corner} />
      <iframe
        src={embedUrl}
        className="vz-real__iframe"
        title={item.title}
        allow="autoplay; encrypted-media; fullscreen"
        allowFullScreen
      />
    </div>
  );
}

// ============================================================
// Standby screen (when no playlist is active)
// ============================================================
function StandbyScreen() {
  return (
    <div className="vz-standby">
      <img src="assets/logo-elsia.png" alt="" className="vz-standby__logo" />
      <div className="vz-standby__title">Aucune diffusion en cours</div>
      <div className="vz-standby__sub">
        Lancez une playlist depuis le contrôleur pour afficher du contenu.
      </div>
      <div className="vz-standby__dot"><span /></div>
    </div>
  );
}

// ============================================================
// Ticker
// ============================================================
function ViewerTicker({ showWeather = true, messages = [], weatherCity = "Bordeaux" }) {
  const [temp, setTemp] = vUseState(null);

  vUseEffect(() => {
    if (!showWeather || !weatherCity) return;
    let cancelled = false;
    const load = async () => {
      try {
        const r = await fetch(`/api/weather?city=${encodeURIComponent(weatherCity)}`);
        const j = await r.json();
        if (!cancelled && j.temp_c !== null && j.temp_c !== undefined) {
          setTemp(Math.round(j.temp_c));
        }
      } catch {}
    };
    load();
    const id = setInterval(load, 600_000); // refresh 10 min
    return () => { cancelled = true; clearInterval(id); };
  }, [showWeather, weatherCity]);

  const msgs = (messages && messages.length > 0)
    ? messages
    : ["✦ Aucun message configuré — Paramètres → Messages du bandeau INFOS"];

  return (
    <div className="viewer-ticker">
      <div className="viewer-ticker__label">INFOS</div>
      <div className="viewer-ticker__track">
        <div className="viewer-ticker__content">
          {msgs.map((m, i) => <span key={i}>{m}</span>)}
        </div>
        <div className="viewer-ticker__content" aria-hidden="true">
          {msgs.map((m, i) => <span key={"d" + i}>{m}</span>)}
        </div>
      </div>
      {showWeather && (
        <div className="viewer-ticker__weather">
          <Icon.Sun size={14} />
          <span>
            <strong>{temp !== null ? `${temp}°` : "—"}</strong> {weatherCity}
          </span>
        </div>
      )}
    </div>
  );
}

// ============================================================
// Main Viewer
// ============================================================
function Viewer({ onExit, activePlaylist }) {
  const [chrome, setChrome] = vUseState(false);
  const [zoneIdx, setZoneIdx] = vUseState({ A: 0, B: 0, C: 0, D: 0 });
  const [settings, setSettings] = vUseState({
    "viewer.show_footer": true,
    "viewer.show_clock": true,
    "viewer.show_logo": true,
    "viewer.show_weather": true,
    "viewer.show_corner_label": true,
    "viewer.show_zone_letter": true,
  });

  // Fetch settings au boot + écoute des updates WS
  vUseEffect(() => {
    fetch("/api/settings").then(r => r.json()).then(setSettings).catch(() => {});
    const onWs = (ev) => {
      const m = ev.detail;
      if (m && m.type === "settings.changed" && m.all) setSettings(m.all);
    };
    window.addEventListener("elsia:ws", onWs);
    return () => window.removeEventListener("elsia:ws", onWs);
  }, []);

  vUseEffect(() => {
    const onMove = () => {
      setChrome(true);
      clearTimeout(window.__chromeT);
      window.__chromeT = setTimeout(() => setChrome(false), 2500);
    };
    window.addEventListener("mousemove", onMove);
    return () => { clearTimeout(window.__chromeT); window.removeEventListener("mousemove", onMove); };
  }, []);

  // Reset when playlist changes
  vUseEffect(() => {
    setZoneIdx({ A: 0, B: 0, C: 0, D: 0 });
  }, [activePlaylist?.id]);

  // Cycle items in each zone every 8 seconds
  vUseEffect(() => {
    if (!activePlaylist) return;
    const id = setInterval(() => {
      setZoneIdx(prev => {
        const next = { ...prev };
        ["A", "B", "C", "D"].forEach(z => {
          const n = (activePlaylist.zones?.[z] || []).length;
          if (n > 0) next[z] = (prev[z] + 1) % n;
        });
        return next;
      });
    }, 8000);
    return () => clearInterval(id);
  }, [activePlaylist?.id]);

  // Filtre éventuellement les items type "met" si désactivés en réglages
  const visibleArr = (z) => {
    const arr = activePlaylist?.zones?.[z] || [];
    if (settings["viewer.show_weather"] === false) return arr.filter(it => it.type !== "met");
    return arr;
  };

  const getItem = (z) => {
    if (!activePlaylist) return null;
    const arr = visibleArr(z);
    if (arr.length === 0) return null;
    return arr[zoneIdx[z] % arr.length];
  };

  const layoutDef = activePlaylist
    ? (VIEWER_LAYOUTS[activePlaylist.layout] || VIEWER_LAYOUTS.quad)
    : VIEWER_LAYOUTS.quad;

  const viewerCls = [
    "viewer",
    settings["viewer.show_footer"]       ? "" : "viewer--hide-footer",
    settings["viewer.show_clock"]        ? "" : "viewer--hide-clock",
    settings["viewer.show_logo"]         ? "" : "viewer--hide-logo",
    settings["viewer.show_corner_label"] ? "" : "viewer--hide-corner-label",
    settings["viewer.show_zone_letter"]  ? "" : "viewer--hide-zone-letter",
  ].filter(Boolean).join(" ");

  return (
    <div className={viewerCls}>
      {!activePlaylist ? (
        <div className="viewer__grid viewer__grid--standby">
          <StandbyScreen />
        </div>
      ) : (
        <div className="viewer__grid" style={{ grid: layoutDef.grid }}>
          {layoutDef.zones.map(z => {
            const item = getItem(z);
            const arr = visibleArr(z);
            return (
              <div key={z} style={{ gridArea: layoutDef.spans?.[z] || "auto", overflow: "hidden" }}>
                <ViewerTile item={item} zone={z} idx={zoneIdx[z]} total={arr.length} />
              </div>
            );
          })}
        </div>
      )}

      {/* Logo overlay */}
      {settings["viewer.show_logo"] !== false && (
        <div className="viewer__brand">
          <img src="assets/logo-elsia.png" alt="Elsia · Groupe ERI" />
        </div>
      )}

      {settings["viewer.show_clock"] !== false && <ViewerClock />}
      {settings["viewer.show_footer"] !== false && (
        <ViewerTicker
          showWeather={settings["viewer.show_weather"] !== false}
          weatherCity={settings["viewer.weather_city"] || "Bordeaux"}
          messages={settings["viewer.ticker_messages"] || []}
        />
      )}

      {/* Hover chrome — exit */}
      <div className={"viewer__chrome" + (chrome ? " viewer__chrome--show" : "")}>
        <button className="btn" onClick={onExit}>
          <Icon.ChevronLeft size={13} /> Retour au contrôleur
        </button>
        <div className="viewer__chrome-meta">
          {activePlaylist ? (
            <>
              <span className="badge badge--live">EN DIFFUSION</span>
              <span style={{ fontSize: 11, fontFamily: "var(--font-mono)" }}>
                {activePlaylist.name} · Open space · 3840 × 2160
              </span>
            </>
          ) : (
            <span style={{ fontSize: 11, fontFamily: "var(--font-mono)" }}>
              Veille · aucune playlist active
            </span>
          )}
        </div>
      </div>
    </div>
  );
}

window.Viewer = Viewer;
window.ViewerTile = ViewerTile;
