/* global React, Icons, Avatar, relTime, abbrev, fmtDuration, podDate, channelHue */
// Tweet, podcast, and news cards. Every card links to its canonical source.
(() => {
  const e = React.createElement;

  // ---------- text linkification ----------
  function linkify(text, urls, hasAttachment) {
    let t = text || "";
    if (hasAttachment) t = t.replace(/\s*https:\/\/t\.co\/\w+\s*$/, "");
    const map = new Map((urls || []).map((u) => [u.tco, u]));
    const parts = [];
    const re = /(https:\/\/t\.co\/\w+)|(https?:\/\/[^\s]+)|(^|[\s(])@(\w{1,20})|(^|[\s(])\$([A-Za-z]{1,6})(?![A-Za-z0-9.])/g;
    let last = 0, m, k = 0;
    while ((m = re.exec(t)) !== null) {
      if (m.index > last) parts.push(t.slice(last, m.index));
      if (m[1]) {
        const u = map.get(m[1]);
        parts.push(e("a", { key: k++, href: (u && u.expanded) || m[1], target: "_blank", rel: "noopener" },
          (u && u.display) || m[1].replace("https://", "")));
      } else if (m[2]) {
        parts.push(e("a", { key: k++, href: m[2], target: "_blank", rel: "noopener" },
          m[2].replace(/^https?:\/\//, "").slice(0, 40)));
      } else if (m[4]) {
        parts.push(m[3]);
        parts.push(e("a", { key: k++, href: `https://x.com/${m[4]}`, target: "_blank", rel: "noopener" }, `@${m[4]}`));
      } else if (m[6]) {
        parts.push(m[5]);
        parts.push(e("a", { key: k++, className: "cashtag", target: "_blank", rel: "noopener",
          href: `https://x.com/search?q=%24${m[6]}` }, `$${m[6]}`));
      }
      last = re.lastIndex;
    }
    if (last < t.length) parts.push(t.slice(last));
    return parts;
  }

  function fmtMs(ms) {
    if (!ms) return null;
    const s = Math.round(ms / 1000);
    return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, "0")}`;
  }
  function MediaGrid({ media, permalink }) {
    if (!media || !media.length) return null;
    const items = media.slice(0, 4);
    return e("div", { className: `tw-media n${items.length}` },
      items.map((m, i) => {
        const isVid = m.type === "video" || m.type === "animated_gif";
        return e("a", { key: i, className: "m", target: "_blank", rel: "noopener",
          href: isVid ? permalink : (m.src || m.thumb) },
          e("img", { src: m.thumb, alt: "", loading: "lazy" }),
          isVid && e("div", { className: "m-play" }, e("span", null, e(Icons.Play, { size: 16 }))),
          isVid && m.duration_ms && e("span", { className: "m-dur" }, fmtMs(m.duration_ms)));
      }));
  }

  function QuotedCard({ q }) {
    if (!q) return null;
    const href = q.id ? `https://x.com/${q.handle || "i"}/status/${q.id}` : null;
    return e("a", { className: "tw-quote", href, target: "_blank", rel: "noopener" },
      e("div", { className: "tw-quote-head" },
        q.avatar_url && e("img", { src: q.avatar_url, alt: "", loading: "lazy" }),
        e("span", { className: "qn" }, q.name || q.handle),
        q.handle && e("span", { className: "qh" }, `@${q.handle}`)),
      q.text && e("div", { className: "tw-quote-body" }, q.text),
      e(MediaGrid, { media: q.media, permalink: href }));
  }

  function LinkCard({ card }) {
    if (!card || !card.title) return null;
    const first = (card.url || "").startsWith("http") ? card.url : null;
    return e("a", { className: "tw-link", href: first, target: "_blank", rel: "noopener" },
      card.image && e("img", { src: card.image, alt: "", loading: "lazy" }),
      e("div", { style: { minWidth: 0 } },
        e("div", { className: "tw-link-t" }, card.title),
        card.description && e("div", { className: "tw-link-d" }, card.description)));
  }

  function Metric({ Icon, value }) {
    if (!value) return null;
    return e("span", { className: "mt" }, e(Icon, { size: 13 }), abbrev(value));
  }

  function TweetCard({ t }) {
    const hasAttachment = !!((t.media && t.media.length) || t.quoted || t.link_card);
    const profile = `https://x.com/${t.handle}`;
    // the "replying to" context line names the target; drop the duplicated
    // leading mention from the body
    let body = t.text;
    if (t.is_reply && t.reply_to) {
      body = body.replace(new RegExp(`^@${t.reply_to}\\s+`, "i"), "");
    }
    const score = t.curation_score;
    const scoreCls = score >= 65 ? "hi" : "mid";
    return e("article", { className: "tw fade-in" },
      e("a", { href: profile, target: "_blank", rel: "noopener",
        "aria-label": `${t.handle} on X`, style: { display: "block", height: 40 } },
        e(Avatar, { src: t.avatar_url, name: t.handle })),
      e("div", { className: "tw-main" },
        e("div", { className: "tw-head" },
          e("a", { className: "tw-name", href: profile, target: "_blank", rel: "noopener" },
            t.author_name || t.handle),
          t.verified ? e(Icons.Check, { size: 11, className: "tw-check" }) : null,
          e("a", { className: "tw-handle", href: profile, target: "_blank", rel: "noopener" }, `@${t.handle}`),
          e("span", { className: "tw-time" },
            score >= 65 ? e("span", { className: "tw-score hi", title: "curation signal, 0 to 100", style: { marginRight: 8 } }, score) : null,
            e("a", { href: t.url, target: "_blank", rel: "noopener", title: t.created_at }, relTime(t.created_unix)))),
        t.is_reply && t.reply_to
          ? e("div", { className: "tw-ctx" }, "replying to ",
              e("a", { href: `https://x.com/${t.reply_to}`, target: "_blank", rel: "noopener" }, `@${t.reply_to}`))
          : null,
        e("div", { className: "tw-body" }, linkify(body, t.urls, hasAttachment)),
        e(MediaGrid, { media: t.media, permalink: t.url }),
        e(QuotedCard, { q: t.quoted }),
        !t.media && !t.quoted ? e(LinkCard, { card: t.link_card }) : null,
        e("div", { className: "tw-foot" },
          e(Metric, { Icon: Icons.Reply, value: t.replies }),
          e(Metric, { Icon: Icons.Repost, value: t.retweets }),
          e(Metric, { Icon: Icons.Heart, value: t.likes }),
          t.views ? e("span", { className: "mt" }, e(Icons.Eye, { size: 13 }), abbrev(t.views)) : null,
          e("a", { className: "open", href: t.url, target: "_blank", rel: "noopener" },
            "View on X", e(Icons.External, { size: 12 }))),
        score >= 65 && t.curation_reason
          ? e("div", { className: "tw-reason" }, t.curation_reason)
          : null));
  }

  function PodcastCard({ p }) {
    const [open, setOpen] = React.useState(false);
    const bullets = p.bullet_summary || [];
    const score = p.interest_score;
    const cls = score >= 80 ? "hi" : score >= 60 ? "md" : "";
    const hue = channelHue(p.channel);
    return e("article", { className: "pod fade-in" },
      e("div", { className: "pod-top" },
        e("a", { href: p.url, target: "_blank", rel: "noopener", "aria-label": p.title },
          e("img", { className: "pod-art", loading: "lazy", alt: "",
            src: `https://i.ytimg.com/vi/${p.video_id}/mqdefault.jpg` })),
        e("div", { className: "pod-main" },
          e("div", { className: "pod-channel" },
            e("span", { className: "ch-dot", style: { background: `hsl(${hue} 45% 55%)` } }),
            e("span", { style: { color: `hsl(${hue} 35% 72%)` } }, p.channel),
            e("span", { className: "pod-meta" },
              podDate(p.published_at), p.duration_sec ? ` · ${fmtDuration(p.duration_sec)}` : "")),
          e("div", { className: "pod-title" },
            e("a", { href: p.url, target: "_blank", rel: "noopener" }, p.title)),
          e("div", { style: { display: "flex", alignItems: "center", gap: 8, marginTop: 5 } },
            score != null ? e("span", { className: `score-chip ${cls}` }, score) : null,
            p.interest_reasoning
              ? e("span", { className: "pod-reason", style: { marginTop: 0 } }, p.interest_reasoning)
              : null))),
      bullets.length
        ? e(React.Fragment, null,
            open && e("ul", { className: "pod-bullets" }, bullets.map((b, i) => e("li", { key: i }, b))),
            e("button", { className: "pod-expand", onClick: () => setOpen(!open) },
              open ? "Hide notes" : `Show notes (${bullets.length})`))
        : null);
  }

  function NewsCard({ n }) {
    const src = n.source === "Bloomberg" ? "bbg" : "wsj";
    return e("article", { className: "news fade-in" },
      e("div", { className: "news-top" },
        e("span", { className: `news-src ${src}` }, e("span", { className: "sd" }), n.source),
        n.feed ? e("span", { className: "news-feed" }, n.feed) : null,
        e("span", { className: "news-time tabnum" }, relTime(n.published_unix))),
      e("a", { className: "news-title", href: n.url, target: "_blank", rel: "noopener" }, n.title),
      n.summary ? e("div", { className: "news-sum" }, n.summary) : null);
  }

  Object.assign(window, { TweetCard, PodcastCard, NewsCard, linkify });
})();
