/* ============================================================
   BITS — shared presentational building blocks
   window: ImgPH, Views, ArticleCard, ReactionBar, EMOJI
   ============================================================ */
(function () {
  const { useApp, H, Icon } = window;

  const EMOJI = [
    { k: "up",         label: "ভালো লাগা", glyph: "▲", icon: "up" },
    { k: "love",       label: "ভালোবাসা",  glyph: "❤" },
    { k: "insightful", label: "অন্তর্দৃষ্টি", glyph: "💡" },
    { k: "sad",        label: "দুঃখজনক",   glyph: "😢" },
    { k: "angry",      label: "ক্ষুব্ধ",     glyph: "😠" },
  ];

  function ImgPH({ label, style, className }) {
    const isUrl = typeof label === "string" && (label.startsWith("http://") || label.startsWith("https://") || label.startsWith("/"));
    if (isUrl) {
      return (
        <div className={"imgph " + (className || "")} style={Object.assign({ background: "#000" }, style || {})}>
          <img src={label} alt="" loading="lazy"
            style={{ width: "100%", height: "100%", objectFit: "cover", display: "block", borderRadius: "inherit" }} />
        </div>
      );
    }
    return (
      <div className={"imgph " + (className || "")} style={style}>
        <span>{label || "image"}</span>
      </div>
    );
  }

  /* ------------- MediaFrame: picks the right tag per media kind -------------
     props: kind (image|video|audio|embed|none), url, thumbnail, mime,
            style, className, autoPlay (embed only), label
     - 'image' → <img>
     - 'video' → <video controls poster=thumbnail>
     - 'embed' → click-to-load YouTube/Vimeo iframe, with poster + ▶ overlay
     - 'audio' → <audio controls>
     - 'none'  → ImgPH placeholder (so the layout never collapses)
  ------------------------------------------------------------------- */
  function toEmbedUrl(url) {
    if (!url) return null;
    let m = url.match(/(?:youtube\.com\/watch\?(?:[^&]*&)*v=|youtu\.be\/|youtube\.com\/embed\/|youtube-nocookie\.com\/embed\/)([\w-]{6,})/i);
    if (m) return "https://www.youtube-nocookie.com/embed/" + m[1] + "?autoplay=1&rel=0";
    m = url.match(/vimeo\.com\/(\d{6,})/i);
    if (m) return "https://player.vimeo.com/video/" + m[1] + "?autoplay=1";
    return null;
  }

  function MediaFrame({ kind, url, thumbnail, mime, style, className, label, showControls = true }) {
    const [loaded, setLoaded] = React.useState(false);
    const k = kind || "none";
    const radiusStyle = Object.assign({ overflow: "hidden", position: "relative" }, style || {});

    if (k === "image") {
      const src = url || thumbnail;
      if (!src) return <ImgPH label={label} style={style} className={className} />;
      return (
        <div className={"imgph " + (className || "")} style={Object.assign({ background: "#000" }, radiusStyle)}>
          <img src={src} alt={label || ""} loading="lazy"
            style={{ width: "100%", height: "100%", objectFit: "cover", display: "block", borderRadius: "inherit" }} />
        </div>
      );
    }

    if (k === "video") {
      if (!url) return <ImgPH label={label || "video"} style={style} className={className} />;
      return (
        <div className={"imgph " + (className || "")} style={Object.assign({ background: "#000" }, radiusStyle)}>
          <video controls={showControls} preload="metadata"
            poster={thumbnail || undefined}
            style={{ width: "100%", height: "100%", objectFit: "cover", display: "block", borderRadius: "inherit" }}>
            <source src={url} type={mime || undefined} />
          </video>
        </div>
      );
    }

    if (k === "embed") {
      const embedSrc = loaded ? toEmbedUrl(url) : null;
      return (
        <div className={"imgph " + (className || "")} style={Object.assign({ background: "#000" }, radiusStyle)}>
          {embedSrc ? (
            <iframe src={embedSrc} title={label || "video"}
              allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
              allowFullScreen
              style={{ width: "100%", height: "100%", border: 0, display: "block", borderRadius: "inherit" }} />
          ) : (
            <button onClick={() => setLoaded(true)} aria-label="ভিডিও চালান"
              style={{ position: "absolute", inset: 0, padding: 0, margin: 0, border: 0, cursor: "pointer", background: "none", borderRadius: "inherit" }}>
              {thumbnail && (
                <img src={thumbnail} alt={label || ""} loading="lazy"
                  style={{ width: "100%", height: "100%", objectFit: "cover", display: "block", borderRadius: "inherit" }} />
              )}
              <span style={{
                position: "absolute", top: "50%", left: "50%", transform: "translate(-50%,-50%)",
                width: 72, height: 72, borderRadius: "50%",
                background: "rgba(0,0,0,0.55)", color: "#fff",
                display: "grid", placeItems: "center", fontSize: 28, pointerEvents: "none",
                backdropFilter: "blur(4px)",
              }}>▶</span>
            </button>
          )}
        </div>
      );
    }

    if (k === "audio") {
      if (!url) return null;
      return (
        <audio controls preload="metadata" src={url} style={{ width: "100%", display: "block" }} />
      );
    }

    return <ImgPH label={label} style={style} className={className} />;
  }

  function isPlayableMedia(a) {
    const k = a && a.mediaKind;
    return k === "video" || k === "embed";
  }

  function Views({ n, light }) {
    return (
      <span className="views" style={light ? { color: "rgba(255,255,255,.85)" } : null}>
        <Icon name="eye" size={14} stroke={1.6} /> {H.numShort(n)}
      </span>
    );
  }

  function VideoMark({ a }) {
    if (a.mediaKind !== "video" && a.mediaKind !== "embed") return null;
    return (
      <span aria-hidden="true" style={{
        position: "absolute", top: 8, left: 8, background: "rgba(0,0,0,.65)", color: "#fff",
        padding: "2px 7px", borderRadius: 999, fontSize: 11, fontWeight: 700, letterSpacing: ".04em",
      }}>▶</span>
    );
  }

  // size: 'lead' | 'tall' | 'row' | 'mini' | 'text'
  function ArticleCard({ a, size = "row" }) {
    const app = useApp();
    const st = app.state.articleState[a.id] || { views: a.views || 0 };
    const cat = H.catBy(a.cat);
    const open = () => app.nav("article", { id: a.id });
    const title   = H.pick(a, "title");
    const excerpt = H.pick(a, "excerpt");
    const author  = H.pick(a, "author");
    const Kicker = () => (
      <button className="kicker bn" onClick={(e) => { e.stopPropagation(); app.nav("category", { slug: a.cat }); }}
        style={{ background: "none", border: 0, padding: 0, cursor: "pointer" }}>{H.pick(cat, "label")}</button>
    );

    if (size === "text") {
      return (
        <article className="ac-text" onClick={open}>
          <Kicker />
          <h4 className="headline-link" style={{ fontSize: 17, margin: "5px 0 7px", cursor: "pointer" }}>{title}</h4>
          <div className="meta"><Views n={st.views} /><span className="dot" />{H.rel(a.ts)}</div>
        </article>
      );
    }
    if (size === "mini") {
      return (
        <article className="ac-mini" onClick={open}
          style={{ display: "grid", gridTemplateColumns: "1fr 86px", gap: 12, cursor: "pointer", alignItems: "start" }}>
          <div>
            <Kicker />
            <h4 className="headline-link" style={{ fontSize: 15.5, margin: "4px 0 6px", lineHeight: 1.3 }}>{title}</h4>
            <div className="meta" style={{ fontSize: 11.5 }}><Views n={st.views} /></div>
          </div>
          <div style={{ position: "relative" }}>
            <ImgPH label={a.img} style={{ width: 86, height: 64, borderRadius: "var(--radius)" }} />
            <VideoMark a={a} />
          </div>
        </article>
      );
    }
    if (size === "lead") {
      return (
        <article className="ac-lead" onClick={open} style={{ cursor: "pointer" }}>
          <div style={{ position: "relative" }}>
            <ImgPH label={a.img} style={{ width: "100%", aspectRatio: "16/9", borderRadius: "var(--radius)", marginBottom: 16 }} />
            <VideoMark a={a} />
          </div>
          <Kicker />
          <h2 className="headline-link" style={{ fontSize: "clamp(26px,3vw,40px)", margin: "8px 0 12px" }}>{title}</h2>
          <p className="ink2" style={{ fontSize: 16.5, lineHeight: 1.55, marginBottom: 12 }}>{excerpt}</p>
          <div className="meta"><span>{author}</span><span className="dot" /><Views n={st.views} /><span className="dot" />{H.rel(a.ts)}</div>
        </article>
      );
    }
    if (size === "tall") {
      return (
        <article className="ac-tall" onClick={open} style={{ cursor: "pointer" }}>
          <div style={{ position: "relative" }}>
            <ImgPH label={a.img} style={{ width: "100%", aspectRatio: "4/3", borderRadius: "var(--radius)", marginBottom: 13 }} />
            <VideoMark a={a} />
          </div>
          <Kicker />
          <h3 className="headline-link" style={{ fontSize: 20, margin: "6px 0 9px" }}>{title}</h3>
          <p className="ink2" style={{ fontSize: 14.5, lineHeight: 1.5, marginBottom: 10 }}>{excerpt}</p>
          <div className="meta"><Views n={st.views} /><span className="dot" />{H.rel(a.ts)}</div>
        </article>
      );
    }
    // row (default)
    return (
      <article className="ac-row" onClick={open}
        style={{ display: "grid", gridTemplateColumns: "1fr 150px", gap: 18, cursor: "pointer", alignItems: "start" }}>
        <div>
          <Kicker />
          <h3 className="headline-link" style={{ fontSize: 19, margin: "5px 0 8px", lineHeight: 1.25 }}>{title}</h3>
          <p className="ink2" style={{ fontSize: 14, lineHeight: 1.5, marginBottom: 9 }}>{excerpt}</p>
          <div className="meta"><Views n={st.views} /><span className="dot" />{H.rel(a.ts)}</div>
        </div>
        <div style={{ position: "relative" }}>
          <ImgPH label={a.img} style={{ width: 150, height: 110, borderRadius: "var(--radius)" }} />
          <VideoMark a={a} />
        </div>
      </article>
    );
  }

  function ReactionBar({ a, compact }) {
    const app = useApp();
    const mine = app.state.myReactions[a.id];
    const rx = (app.state.articleState[a.id] || {}).reactions || {};
    const total = Object.values(rx).reduce((s, n) => s + n, 0);
    return (
      <div className="reactbar" style={{ display: "flex", flexWrap: "wrap", alignItems: "center", gap: 8 }}>
        {EMOJI.map(e => {
          const active = mine === e.k;
          return (
            <button key={e.k} title={e.label} onClick={() => app.react(a.id, e.k)}
              className="react-pill" data-active={active}
              style={{
                display: "inline-flex", alignItems: "center", gap: 6,
                border: "1px solid " + (active ? "var(--accent)" : "var(--line)"),
                background: active ? "var(--accent-wash)" : "var(--surface)",
                color: active ? "var(--accent-ink)" : "var(--ink-2)",
                padding: "7px 11px", borderRadius: 999, fontSize: 13.5, fontWeight: 600,
                transition: "all .14s ease",
              }}>
              <span style={{ fontSize: e.k === "up" ? 11 : 15, lineHeight: 1 }}>{e.glyph}</span>
              <span style={{ fontVariantNumeric: "tabular-nums" }}>{H.numShort(rx[e.k] || 0)}</span>
            </button>
          );
        })}
        {!compact && <span className="muted" style={{ fontSize: 12.5, marginLeft: 4 }}>{H.numShort(total)} {H.t("reactions")}</span>}
      </div>
    );
  }

  Object.assign(window, { ImgPH, MediaFrame, isPlayableMedia, Views, ArticleCard, ReactionBar, EMOJI });
})();
