// Published & Live — see everything that's gone out and what's queued.
// Phase 1 (local): published/scheduled/failed feed with per-channel delivery
// status and timestamps. Phase 2 (needs OAuth): pull real live posts + metrics
// and permalinks back from each platform.

const PUB_STATUS = {
  published: { label: "Live", cls: "ok" },
  partial: { label: "Partially live", cls: "warn" },
  processing: { label: "Publishing…", cls: "info" },
  scheduled: { label: "Scheduled", cls: "info" },
  needs_approval: { label: "In approval", cls: "warn" },
  changes_requested: { label: "Changes requested", cls: "warn" },
  failed: { label: "Failed", cls: "danger" },
  blocked: { label: "Blocked", cls: "danger" },
  rejected: { label: "Rejected", cls: "danger" },
  draft: { label: "Draft", cls: "muted" }
};

// Build the outbound "View post" link. Some stored permalinks are broken —
// Facebook's Graph API returns a RELATIVE path ("/reel/123/") for Video/Reel
// objects instead of an absolute URL, and older X posts stored the
// /i/web/status/:id compatibility redirect instead of the canonical
// username-based link. Reconstructing here (rather than trusting the raw
// stored value) fixes already-published historical posts immediately, with
// no data migration, and stays correct even if the stored value is stale.
function resolvePostViewUrl(platform, chanStatus, fallbackUrl, integ) {
  const raw = chanStatus.url || fallbackUrl || "";
  if (platform === "x") {
    const handle = integ && integ.handle ? String(integ.handle).replace(/^@/, "") : "";
    if (handle && chanStatus.providerPostId) return `https://x.com/${handle}/status/${chanStatus.providerPostId}`;
    if (chanStatus.providerPostId) return `https://x.com/i/web/status/${chanStatus.providerPostId}`;
    return /^https?:\/\//i.test(raw) ? raw : null;
  }
  if (/^https?:\/\//i.test(raw)) return raw;
  if (platform === "facebook") {
    if (raw.startsWith("/")) return `https://www.facebook.com${raw}`;
    if (chanStatus.providerPostId) return `https://www.facebook.com/${chanStatus.providerPostId}`;
  }
  if (platform === "instagram" && raw.startsWith("/")) return `https://www.instagram.com${raw}`;
  return null; // an unrecognized relative/garbage value — don't link somewhere wrong
}

function PublishedPage() {
  const hub = window.useClearCast();
  const data = hub.data || {};
  const posts = data.posts || [];
  const [tab, setTab] = React.useState("live");

  const counts = {
    live: posts.filter((p) => p.status === "published").length,
    scheduled: posts.filter((p) => p.status === "scheduled").length,
    attention: posts.filter((p) => ["failed", "blocked"].includes(p.status)).length,
    all: posts.length
  };
  const filtered = posts.filter((p) => {
    if (tab === "live") return p.status === "published";
    if (tab === "scheduled") return p.status === "scheduled";
    if (tab === "attention") return ["failed", "blocked"].includes(p.status);
    return true;
  }).sort((a, b) => (b.updatedAt || b.createdAt || "").localeCompare(a.updatedAt || a.createdAt || ""));

  const retry = async (post) => { try { await hub.actions.publishPost(post.id, true); } catch (e) { /* toast handled */ } };
  const integrationsById = Object.fromEntries((data.integrations || []).map((i) => [i.id, i]));

  const CHAN_STATE = {
    published: { label: "Live", color: "var(--accent-2)" },
    processing: { label: "Publishing…", color: "var(--text-2)" },
    failed: { label: "Failed", color: "var(--danger)" },
    blocked: { label: "Blocked", color: "var(--danger)" },
    pending: { label: "Pending", color: "var(--text-3)" }
  };

  return (
    <div className="page published-page">
      <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 12, marginBottom: 16 }}>
        {[
          ["Live posts", counts.live, "var(--accent-2)"],
          ["Scheduled", counts.scheduled, "var(--text)"],
          ["Needs attention", counts.attention, counts.attention ? "var(--danger)" : "var(--text)"],
          ["Total", counts.all, "var(--text)"]
        ].map(([label, value, color]) => (
          <div key={label} className="card" style={{ padding: 14 }}>
            <div className="muted" style={{ fontSize: 11.5 }}>{label}</div>
            <div style={{ fontSize: 22, fontWeight: 750, color, marginTop: 2 }}>{value}</div>
          </div>
        ))}
      </div>

      <div className="tabs" style={{ marginBottom: 14 }}>
        {[["live", "Live"], ["scheduled", "Scheduled"], ["attention", "Needs attention"], ["all", "All"]].map(([id, label]) => (
          <button key={id} className={`tab ${tab === id ? "active" : ""}`} onClick={() => setTab(id)}>{label} {counts[id] ? counts[id] : ""}</button>
        ))}
      </div>

      <div style={{ display: "grid", gap: 10 }}>
        {filtered.map((post) => {
          const status = PUB_STATUS[post.status] || PUB_STATUS.draft;
          const lastAttempt = (post.publishAttempts || [])[0];
          const chStatus = post.channelStatus || {};
          const urlByPlatform = Object.fromEntries((post.publishedUrls || []).map((u) => [u.platform, u.url]));
          // Channels that failed/blocked on the last attempt — these are what "Retry
          // failed channels" re-fires (publishPostNow skips already-published ones).
          const failedChannels = (post.platforms || []).filter((p) => ["failed", "blocked"].includes((chStatus[p] || {}).status));
          const hasChannelDetail = (post.platforms || []).some((p) => chStatus[p]);
          return (
            <div key={post.id} className="card published-row" style={{ padding: 14 }}>
              <div className="published-platforms">
                {(post.platforms || []).map((id) => <PlatformIcon key={id} id={id} size={20} />)}
              </div>
              <div className="published-body">
                <div className="published-caption">{post.caption || "Untitled post"}</div>
                <div className="published-meta muted">
                  <span>{post.date} · {post.time}</span>
                  {post.status === "published" && lastAttempt && <span>· delivered {new Date(lastAttempt.finishedAt).toLocaleDateString()}</span>}
                  {post.lastPublishError && post.status !== "published" && <span style={{ color: "var(--danger)" }}>· {post.lastPublishError}</span>}
                </div>
                {/* Per-channel delivery: real permalink when live, reason + fix when failed. */}
                {hasChannelDetail && (
                  <div style={{ display: "flex", flexDirection: "column", gap: 5, marginTop: 8 }}>
                    {(post.platforms || []).map((p) => {
                      const cs = chStatus[p];
                      if (!cs) return null;
                      const meta = CHAN_STATE[cs.status] || CHAN_STATE.pending;
                      const url = resolvePostViewUrl(p, cs, urlByPlatform[p], integrationsById[p]);
                      const name = (window.Platforms && window.Platforms[p] && window.Platforms[p].name) || p;
                      return (
                        <div key={p} style={{ display: "flex", alignItems: "flex-start", gap: 8, fontSize: 11.5 }}>
                          <PlatformIcon id={p} size={14} />
                          <span style={{ fontWeight: 600, minWidth: 64 }}>{name}</span>
                          <span style={{ color: meta.color, fontWeight: 600 }}>{meta.label}</span>
                          {cs.status === "published" && url && (
                            <a href={url} target="_blank" rel="noopener noreferrer" style={{ color: "var(--accent-2)" }}>View post ↗</a>
                          )}
                          {cs.status !== "published" && cs.human && (
                            <span className="muted" style={{ flex: 1 }}>— {cs.human.reason}{cs.human.fix ? ` ${cs.human.fix}` : ""}</span>
                          )}
                          {cs.status !== "published" && !cs.human && cs.error && (
                            <span className="muted" style={{ flex: 1 }}>— {cs.error}</span>
                          )}
                        </div>
                      );
                    })}
                  </div>
                )}
              </div>
              <div className="published-right">
                <span className={`pill ${status.cls}`} style={{ padding: "3px 9px", fontSize: 11 }}>{status.label}</span>
                {failedChannels.length > 0 && (
                  <button className="btn btn-sm btn-primary" onClick={() => retry(post)} title={`Re-fire only the channels that didn't post: ${failedChannels.join(", ")}`}>
                    Retry failed {failedChannels.length > 1 ? `(${failedChannels.length})` : ""}
                  </button>
                )}
                {post.status === "scheduled" && (
                  <button className="btn btn-sm" onClick={() => { sessionStorage.setItem("clearcast-edit-post-id", post.id); window.location.hash = "create"; }}>Edit</button>
                )}
              </div>
            </div>
          );
        })}
        {!filtered.length && (
          <div className="card" style={{ padding: 32, textAlign: "center" }}>
            <div style={{ fontWeight: 650, marginBottom: 4 }}>Nothing here yet</div>
            <div className="muted" style={{ fontSize: 12.5, marginBottom: 14 }}>{tab === "live" ? "Published posts will appear here once you publish." : tab === "scheduled" ? "Scheduled posts will show up here." : "No posts need attention — nice."}</div>
            <button className="btn btn-primary" onClick={() => { window.location.hash = "create"; }}><Icon.Edit width="14" height="14" /> Create a post</button>
          </div>
        )}
      </div>

      <div className="muted" style={{ fontSize: 11.5, marginTop: 14, textAlign: "center" }}>
        Each connected channel shows its live permalink once published. On-platform metrics sync automatically.
      </div>
    </div>
  );
}

window.PublishedPage = PublishedPage;
