// MomentIQ Creator Portal — TikTok feed picker (production)
// Feed:        GET /api/tiktok-posts?handle=@x&campaign=Y   (server-side socialplatform key)
// AI prescan:  GET /api/prescan?handle=@x&campaign=Y        (cached Opus transcript scan, if ops pre-ran it)
// Suggestions arrive on the feed response (caption match); a cached prescan upgrades them.

/* ---------- Live fetch via our own API ---------- */
async function fetchCreatorFeed(handle, campaign) {
  const clean = String(handle || "").trim().replace(/^@/, "");
  if (!clean) return { error: "no handle", posts: null };
  try {
    // Forward the creator credential from the personalized link — the feed
    // APIs are gated (bt= brief token, or t= link token + email).
    const linkParams = new URLSearchParams(window.location.search);
    let cred = "";
    if (linkParams.get("bt")) cred = `&bt=${encodeURIComponent(linkParams.get("bt"))}`;
    else if (linkParams.get("t")) cred = `&t=${encodeURIComponent(linkParams.get("t"))}&email=${encodeURIComponent(linkParams.get("email") || "")}`;
    const qs = `handle=${encodeURIComponent("@" + clean)}&campaign=${encodeURIComponent(campaign || "")}${cred}`;
    const res = await fetch(`/api/tiktok-posts?${qs}`, { signal: AbortSignal.timeout(20000) });
    const data = await res.json().catch(() => ({}));
    if (!res.ok || !data.ok || !Array.isArray(data.posts) || !data.posts.length) {
      throw new Error(data.error || `feed ${res.status}`);
    }
    let posts = data.posts.map((p) => ({
      id: String(p.id),
      url: p.url,
      desc: String(p.desc || ""),
      views: p.stats ? p.stats.plays : null,
      likes: p.stats ? p.stats.likes : null,
      created: p.createTime ? new Date(p.createTime * 1000) : null,
      cover: p.cover || null,
      suggested: !!p.suggested,
    }));
    // Upgrade caption suggestions with a cached AI transcript scan when one exists
    try {
      const pre = await fetch(`/api/prescan?${qs}`, { signal: AbortSignal.timeout(6000) }).then((r) => r.json());
      if (pre && pre.found && Array.isArray(pre.posts)) {
        const verdicts = new Map(pre.posts.map((p) => [String(p.id), !!p.suggested]));
        posts = posts.map((p) => (verdicts.has(p.id) ? { ...p, suggested: verdicts.get(p.id) } : p));
      }
    } catch (e) { /* prescan is best-effort */ }
    return { error: null, avatarUrl: null, posts };
  } catch (e) {
    // Feed unavailable (private account, upstream block, bad handle) — caller falls back to paste mode
    return { error: e.message, avatarUrl: null, posts: null };
  }
}

/* ---------- Suggestion set from the posts' own flags ---------- */
function suggestCampaignPosts(posts) {
  const hits = new Set();
  (posts || []).forEach((p) => { if (p.suggested) hits.add(p.id); });
  return hits;
}

/* ---------- helpers ---------- */
const fmtCount = (n) => n == null ? "" : n >= 1e6 ? (n / 1e6).toFixed(1).replace(/\.0$/, "") + "M" : n >= 1e3 ? Math.round(n / 1e3) + "K" : String(n);
const fmtAgo = (d) => {
  if (!d) return "";
  const days = Math.max(1, Math.round((Date.now() - d.getTime()) / 86400000));
  return days < 7 ? `${days}d` : days < 30 ? `${Math.round(days / 7)}w` : `${Math.round(days / 30)}mo`;
};

/* ---------- Creator avatar ---------- */
function CreatorAvatar({ creator, feed, size = 48 }) {
  const url = (feed && feed !== "loading" && feed.avatarUrl) || (creator && creator.photo);
  if (url) return <img className="cp-avatar-img" style={{ width: size, height: size }} src={url} alt={creator.handle} />;
  return (
    <span className="cp-greet-avatar" style={{ width: size, height: size, fontSize: size * 0.38 }}>
      {creator.handle.replace("@", "").charAt(0).toUpperCase()}
    </span>
  );
}

/* ---------- FeedPicker component ---------- */
function FeedPicker({ feed, selected, onToggle, suggested, orderedCount, showAll, onShowAll, onPasteMode, onSelectAllTagged, brandName }) {
  const tagged = feed.posts.filter((p) => suggested.has(p.id));
  const others = feed.posts.filter((p) => !suggested.has(p.id));
  const shownOthers = showAll ? others : others.slice(0, 4);
  const remaining = Math.max(0, orderedCount - selected.size);
  const manyMatched = tagged.length >= 4; // "we found a lot" state
  const allTaggedSelected = tagged.length > 0 && tagged.every((p) => selected.has(p.id));

  const card = (p) => {
    const isSel = selected.has(p.id);
    const isSug = suggested.has(p.id);
    return (
      <button type="button" key={p.id} onClick={() => onToggle(p.id)}
        className={"cp-post" + (isSel ? " is-selected" : "")} aria-pressed={isSel}>
        <span className="cp-post-thumb" style={p.cover
          ? { backgroundImage: `url(${p.cover})` }
          : { background: `linear-gradient(160deg, oklch(0.32 0.09 ${p.hue || 285}), oklch(0.18 0.05 ${(p.hue || 285) + 30}))` }}>
          {!p.cover && (
            <svg width="22" height="22" viewBox="0 0 24 24" fill="rgba(255,255,255,0.55)" aria-hidden="true"><path d="M8 5v14l11-7z"></path></svg>
          )}
          {isSug && <span className="cp-post-sug"><IconSparkle size={10} /> tagged</span>}
          <span className="cp-post-check">{isSel && <IconCheck size={13} strokeWidth={3} />}</span>
          {p.views != null && <span className="cp-post-views">{fmtCount(p.views)} views</span>}
        </span>
        <span className="cp-post-desc">{p.desc}</span>
        <span className="cp-post-meta">{fmtAgo(p.created)} ago{p.likes != null ? ` · ${fmtCount(p.likes)} likes` : ""}</span>
      </button>
    );
  };

  return (
    <div className="cp-feed">
      {tagged.length > 0 && (
        <div className={"cp-feed-sect" + (manyMatched ? " is-many" : "")}>
          <div className="cp-feed-sect-head">
            <span className="cp-feed-sect-lead">
              <IconSparkle size={15} />
              {manyMatched
                ? <span>We found <strong>{tagged.length} posts</strong> that look like {brandName}</span>
                : <span>Tagged from your posts</span>}
            </span>
            <span className="cp-feed-tools">
              {tagged.length > 1 && onSelectAllTagged && (
                <button type="button" className="cp-linklike" onClick={() => onSelectAllTagged(!allTaggedSelected)}>
                  {allTaggedSelected ? "Clear" : "Select all"}
                </button>
              )}
            </span>
          </div>
          {manyMatched && (
            <p className="cp-feed-sect-note">Pre-selected the {Math.min(orderedCount, tagged.length)} you ordered — tap any to adjust.</p>
          )}
          <div className="cp-feed-grid">{tagged.map(card)}</div>
        </div>
      )}
      <div className="cp-feed-head">
        <span className={"cp-feed-remaining" + (remaining === 0 ? " is-done" : "")}>
          {remaining === 0
            ? <React.Fragment><IconCheck size={13} strokeWidth={2.6} /> All {orderedCount} {orderedCount === 1 ? "post" : "posts"} accounted for</React.Fragment>
            : <React.Fragment><strong>{remaining}</strong>&nbsp;more to add</React.Fragment>}
        </span>
        <span className="cp-feed-tools">
          {onPasteMode && <button type="button" className="cp-linklike" onClick={onPasteMode}>paste links instead</button>}
        </span>
      </div>
      <div className="cp-feed-grid">{shownOthers.map(card)}</div>
      {!showAll && others.length > 4 && (
        <button type="button" className="cp-add-link" onClick={onShowAll}>
          <IconPlus size={14} strokeWidth={2.2} /> Show {others.length - 4} more
        </button>
      )}
    </div>
  );
}

function FeedSkeleton() {
  return (
    <div className="cp-feed-grid" aria-hidden="true">
      {[0, 1, 2, 3].map((i) => <span key={i} className="cp-post-skel" style={{ animationDelay: `${i * 0.12}s` }}></span>)}
    </div>
  );
}

/* ---------- Analyzing splash (shown while the real scan runs) ---------- */
const ANALYZE_STEPS = [
  "Pulling your 30 most recent posts",
  "Transcribing audio",
  "Matching posts to the campaign brief",
  "Tagging your deliverables",
];
function AnalyzingPanel({ handle, brand }) {
  const [i, setI] = useState(0);
  useEffect(() => {
    const t = setInterval(() => setI((p) => Math.min(p + 1, ANALYZE_STEPS.length - 1)), 620);
    return () => clearInterval(t);
  }, []);
  return (
    <div className="cp-analyze" role="status" aria-live="polite">
      <div className="cp-analyze-orb">
        <span className="cp-analyze-ring"></span>
        <IconSparkle size={26} />
      </div>
      <h3 className="cp-analyze-title">Analyzing your profile for campaign deliverables</h3>
      <p className="cp-analyze-sub">Scanning {handle}{brand ? ` for ${brand} posts` : ""}…</p>
      <ul className="cp-analyze-steps">
        {ANALYZE_STEPS.map((s, j) => (
          <li key={s} className={j < i ? "is-done" : j === i ? "is-active" : ""}>
            <span className="cp-analyze-dot">{j < i ? <IconCheck size={11} strokeWidth={3} /> : null}</span>
            {s}
          </li>
        ))}
      </ul>
    </div>
  );
}

Object.assign(window, { fetchCreatorFeed, suggestCampaignPosts, FeedPicker, FeedSkeleton, AnalyzingPanel, CreatorAvatar });
