/* Robindex v2 — Persona market: card grid with distill/update/claim/reward state,
   plus the paid-update modal. */
const { useState: mkS } = React;

function personaPriceLine(reg, lang) {
  const E = window.RXE;
  const b = E.callBreakdown(reg, "dspro", 9000, 1400, false);
  return { from: b.total, parts: b };
}

function PersonaCard2({ reg, lang, onAsk, onUpdate, onClaim, onView }) {
  const { Icon, Avatar } = window.RXC;
  const E = window.RXE;
  const L = (en, zh) => (lang === "zh" ? zh : en);
  const kol = kolAdapter(reg);
  const stale = E.staleFor(reg.updatedAt) && reg.status === "live";
  const price = personaPriceLine(reg, lang);
  const distilling = reg.status === "distilling";
  return (
    <div className={"pcard" + (distilling ? " distilling" : "")} style={{ "--glow": reg.accent + "22" }} data-screen-label={"persona-" + reg.handle}>
      <div className="pcard-top">
        <Avatar kol={kol} size={42} radius={12} />
        <div style={{ minWidth: 0, flex: 1 }}>
          <div className="pcard-nm">
            <span style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{reg.name}</span>
            <ClaimBadge claimed={reg.claimed} />
          </div>
          <div className="pcard-h">@{reg.handle} · {reg.followers}</div>
        </div>
        {distilling
          ? <span className="badge-distill"><span className="dot"></span>{T2("distillingTag")}</span>
          : reg.justLive && <span className="badge-claim">{T2("justLive")}</span>}
      </div>
      <div className="pcard-role">{typeof reg.role === "object" ? (reg.role[lang] || reg.role.en) : reg.role}</div>

      {distilling ? (
        <React.Fragment>
          <div className="dst-row">
            <span className="pct">{Math.floor(reg.distillPct)}%</span>
            <div className="rw-bar amber" style={{ flex: 1 }}><i style={{ width: reg.distillPct + "%" }}></i></div>
            <span>{T2("distillingEta")(reg.distillEtaMin)}</span>
          </div>
          <div className="pcard-stats">
            <span><b>{reg.tweetsTotal.toLocaleString()}</b> {T2("crPosts")}</span>
            <span>{T2("creatorLine")(reg.creator.you ? "you" : reg.creator.by)}</span>
          </div>
        </React.Fragment>
      ) : (
        <React.Fragment>
          <div className="pcard-stats">
            <span><b>{reg.tweetsTotal.toLocaleString()}</b> {T2("crPosts")}</span>
            <span><b>{(reg.calls || 0).toLocaleString()}</b> {T2("cardCalls")}</span>
            <span>{T2("creatorLine")(reg.creator.you ? "you" : reg.creator.by)}</span>
          </div>
          {reg.creator && reg.creator.earned < reg.creator.cap && (
            <RewardBar label={T2("rewardLine")} earned={reg.creator.earned} cap={reg.creator.cap} live={reg.creator.you} />
          )}
          {reg.updater && reg.updater.earned < reg.updater.cap && (
            <RewardBar label={T2("updRewardLine")} earned={reg.updater.earned} cap={reg.updater.cap} live={reg.updater.you} amber />
          )}
          <div className="pcard-upd">
            <Icon name="clock" size={12} />
            <span>{T2("cardUpdated")}: <span className="ts">{E.fmtDT(reg.updatedAt)}</span></span>
            {reg.newSince > 0 && <span className="new">{T2("cardNew")(reg.newSince)}</span>}
            {stale
              ? <button className="btn-upd" onClick={() => onUpdate(reg)}><Icon name="refresh" size={11} />{T2("cardUpdateBtn")}</button>
              : <span style={{ marginLeft: "auto", color: "var(--up)", display: "inline-flex", gap: 4, alignItems: "center" }}><Icon name="check" size={11} />{T2("cardUpToDate")}</span>}
          </div>
          <div className="pcard-price">
            <span>{T2("cardFrom")}</span><b>{E.usd(price.from, price.from < 0.1 ? 3 : 2)}</b><span>/ {T2("cardPerCall")}</span>
            {price.parts.kolFee > 0 && <span>· {T2("chKol")} {E.usd(price.parts.kolFee)}</span>}
          </div>
          <div className="pcard-cta">
            <button className="btn-ask" onClick={() => onAsk(reg)}><Icon name="sparkles" size={13} />{T2("cardAsk")}</button>
            {reg.claimed && reg.claimed.you ? (
              <button className="btn-ghost" onClick={() => onClaim(reg)} title={L("Manage", "管理")}><Icon name="crown" size={11} />{L("Manage", "管理")}</button>
            ) : !reg.claimed && (
              <button className="btn-ghost" onClick={() => onClaim(reg)} title={T2("clTag")}><Icon name="xLogo" size={11} />{T2("clTag")}</button>
            )}
          </div>
        </React.Fragment>
      )}
    </div>
  );
}

function MarketPage({ lang, regs, onAsk, onCreate, onClaim, onUpdate }) {
  const { Icon } = window.RXC;
  const [q, setQ] = mkS("");
  const [f, setF] = mkS("all");
  const filters = [["all", T2("mktAll")], ["live", T2("mktLive")], ["distilling", T2("mktDistilling")], ["claimed", T2("mktClaimed")], ["mine", T2("mktMine")]];
  const list = (Array.isArray(regs) ? regs : []).filter((r) => {
    if (q && !(r.handle + r.name).toLowerCase().includes(q.toLowerCase().replace(/https?:\/\/(x|twitter)\.com\//, "").trim())) return false;
    if (f === "live") return r.status === "live";
    if (f === "distilling") return r.status === "distilling";
    if (f === "claimed") return !!r.claimed;
    if (f === "mine") return (r.creator && r.creator.you) || (r.updater && r.updater.you) || (r.claimed && r.claimed.you);
    return true;
  });
  return (
    <div className="v2-page" data-screen-label="market">
      <div className="v2-wrap">
        <div className="v2-head">
          <h1>{T2("mktTitle")}</h1>
          <p>{T2("mktSub")}</p>
        </div>
        <div className="mkt-tools">
          <div className="mkt-search">
            <Icon name="search" size={14} color="var(--faint)" />
            <input value={q} onChange={(e) => setQ(e.target.value)} placeholder={T2("mktSearch")} />
          </div>
          <div className="mkt-filters">
            {filters.map(([id, lb]) => (
              <button key={id} className={"mkt-f" + (f === id ? " on" : "")} onClick={() => setF(id)}>{lb}</button>
            ))}
          </div>
        </div>
        <div className="mkt-grid">
          {list.map((r) => (
            <PersonaCard2 key={r.id} reg={r} lang={lang} onAsk={onAsk} onUpdate={onUpdate} onClaim={onClaim} />
          ))}
          <button className="pcard ghosty" onClick={onCreate}>
            <Icon name="plus" size={20} color="var(--accent)" />
            <h3>{T2("notFoundTitle")}</h3>
            <p>{T2("notFoundBody")}</p>
            <span className="btn-upd" style={{ marginLeft: 0 }}>{T2("notFoundCta")}</span>
          </button>
        </div>
      </div>
    </div>
  );
}

/* ---------------- paid update modal ---------------- */
/* Spec: on mount, parallel-fetch RXAPI.updateEstimate(reg.id) and
   RXAPI.wallet({limit:1}); server returns {estimate,quoteId,newTweets,
   refresh} | {error}. wallet.balances cash+reward shown display-only.
   States loading/error/up_to_date/update_in_progress are bilingual and
   accessible (role=status / role=alert). Estimate display uses only
   server estimate/newTweets. Pay is async RXAPI.updatePay(reg.id,
   quoteId) with busy guard; insufficient → onTopup(need); success →
   queued completion page. Exceptions restore busy. No setState after
   unmount. Amounts are server-authoritative; balance is display-only.
   Takeover rule notice preserved. */
function UpdateModal({ reg, onClose, onTopup }) {
  const { useState: uS, useEffect: uE, useRef: uR } = React;
  const { Icon } = window.RXC;
  const E = window.RXE, C = E.cfg();
  const zh = window.RXI.lang === "zh";
  // phase: loading | error | up_to_date | update_in_progress | ready | queued
  const [phase, setPhase] = uS("loading");
  const [est, setEst] = uS(null);
  const [newTweets, setNewTweets] = uS(0);
  const [quoteId, setQuoteId] = uS(null);
  const [bal, setBal] = uS({ cash: 0, reward: 0 });
  const [errCode, setErrCode] = uS(null);
  const [tick, setTick] = uS(0);
  const [busy, setBusy] = uS(false);
  const [payErr, setPayErr] = uS(null);
  const alive = uR(true);

  uE(() => () => { alive.current = false; }, []);

  uE(() => {
    let cancelled = false;
    (async () => {
      setPhase("loading"); setErrCode(null);
      try {
        const [estRes, walRes] = await Promise.all([
          window.RXAPI.updateEstimate(reg.id),
          window.RXAPI.wallet({ limit: 1 }),
        ]);
        if (cancelled) return;
        if (walRes && !walRes.error) {
          const b = walRes.balances || {};
          setBal({ cash: b.cash || 0, reward: b.reward || 0 });
        }
        if (estRes && estRes.error) {
          if (estRes.error === "up_to_date") { setPhase("up_to_date"); return; }
          if (estRes.error === "update_in_progress") { setPhase("update_in_progress"); return; }
          setErrCode(estRes.error); setPhase("error"); return;
        }
        if (!estRes || !estRes.estimate) {
          setErrCode("request_failed"); setPhase("error"); return;
        }
        const nt = estRes.newTweets || 0;
        if (nt === 0) { setPhase("up_to_date"); return; }
        setEst(estRes.estimate);
        setQuoteId(estRes.quoteId);
        setNewTweets(nt);
        setPhase("ready");
      } catch (_) {
        if (!cancelled) { setErrCode("network_error"); setPhase("error"); }
      }
    })();
    return () => { cancelled = true; };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [reg.id, tick]);

  const balTotal = bal.cash + bal.reward;

  const pay = async () => {
    if (busy || !quoteId) return;
    setBusy(true); setPayErr(null);
    try {
      const r = await window.RXAPI.updatePay(reg.id, quoteId);
      if (!alive.current) return;
      if (r && r.error) {
        if (r.error === "insufficient" && typeof r.need === "number") {
          onTopup(r.need);
        } else {
          setPayErr(r.error);
        }
        return;
      }
      if (r && r.ok) { window.dispatchEvent(new CustomEvent("rx2:refresh")); setPhase("queued"); return; }
      setPayErr("request_failed");
    } catch (_) {
      if (alive.current) setPayErr("network_error");
    } finally {
      if (alive.current) setBusy(false);
    }
  };

  const loadingText = zh ? "加载中…" : "Loading…";
  const errText = errCode === "network_error"
    ? (zh ? "网络错误，请重试" : "Network error, please retry")
    : errCode === "unauthorized"
      ? (zh ? "未登录，请先登录" : "Not signed in")
      : errCode === "account_banned"
        ? (zh ? "账户已被冻结" : "Account is frozen")
        : (zh ? "加载失败，请重试" : "Failed to load, please retry");
  const retryLabel = zh ? "重试" : "Retry";
  const upToDateText = zh ? "该分身已是最新，无需更新" : "This persona is already up to date — no update needed";
  const inProgressText = zh ? "该分身已有更新在进行中，请稍后再试" : "An update is already in progress for this persona — please retry later";
  const queuedTitle = zh ? "更新已加入队列" : "Update queued";
  const queuedBody = zh ? "我们会在后台拉取新帖并刷新人格，完成后该分身自动恢复最新。" : "We'll fetch the new posts and refresh the persona in the background — it'll be live again shortly.";
  const payErrText = payErr && (() => {
    const m = {
      unauthorized: zh ? "未登录" : "Not signed in",
      account_banned: zh ? "账户已被冻结" : "Account is frozen",
      insufficient: zh ? "余额不足" : "Insufficient credits",
      network_error: zh ? "网络错误，请重试" : "Network error, please retry",
      request_failed: zh ? "请求失败，请重试" : "Request failed, please retry",
    };
    return m[payErr] || (zh ? "更新失败，请重试" : "Update failed, please retry");
  })();
  const submitting = zh ? "提交中…" : "Submitting…";

  if (phase === "queued") {
    const shareHandle = reg.handle || reg.id;
    const shareText = T2("upShareBody")(shareHandle) + "\n\nhttps://app.robindex.ai/k/" + encodeURIComponent(shareHandle) + "?utm_source=update&utm_medium=share";
    return (
      <Modal2 title={T2("upTitle")(reg.handle)} icon="refresh" onClose={onClose}>
        <div className="dst-panel" style={{ padding: "24px 6px" }} role="status">
          <Icon name="check" size={30} color="var(--up)" />
          <h2 style={{ marginTop: 10 }}>{queuedTitle}</h2>
          <p>{queuedBody}</p>
          <p style={{ color: "var(--faint)", font: "400 12px var(--sans)", marginTop: 4 }}>{T2("upReward")(C.rewardMult)}</p>
        </div>
        <a
          className="btn-ghost"
          href={"https://x.com/intent/post?text=" + encodeURIComponent(shareText)}
          target="_blank"
          rel="noopener noreferrer"
          style={{ display: "inline-flex", alignItems: "center", gap: 6, marginTop: 10, textDecoration: "none" }}
          onClick={() => { try { if (window.RXA) window.RXA.track("updater_share_clicked", { kol_id: reg.id, source: "update_queued" }); } catch (_) {} }}
        >
          <Icon name="xLogo" size={13} />{T2("upShareInvite")}
        </a>
        <button className="x2-primary" onClick={onClose} style={{ marginTop: 10 }}>{T2("crGoAsk")}</button>
      </Modal2>
    );
  }

  if (phase === "up_to_date") {
    return (
      <Modal2 title={T2("upTitle")(reg.handle)} icon="refresh" onClose={onClose}>
        <div className="dst-panel" style={{ padding: "24px 6px" }} role="status">
          <Icon name="check" size={30} color="var(--up)" />
          <h2 style={{ marginTop: 10 }}>{T2("cardUpToDate")}</h2>
          <p>{upToDateText}</p>
        </div>
        <button className="x2-primary" onClick={onClose}>{T2("crGoAsk")}</button>
      </Modal2>
    );
  }

  if (phase === "update_in_progress") {
    return (
      <Modal2 title={T2("upTitle")(reg.handle)} icon="refresh" onClose={onClose}>
        <div className="dst-panel" style={{ padding: "24px 6px" }} role="status">
          <Icon name="clock" size={30} color="var(--amber)" />
          <h2 style={{ marginTop: 10 }}>{inProgressText}</h2>
        </div>
        <button className="x2-primary" onClick={onClose}>{T2("crGoAsk")}</button>
      </Modal2>
    );
  }

  if (phase === "error") {
    return (
      <Modal2 title={T2("upTitle")(reg.handle)} icon="refresh" onClose={onClose}>
        <div className="v2-card" style={{ padding: 18 }}>
          <div className="x2-note x2-danger" role="alert"><Icon name="shield" size={13} style={{ flex: "none", marginTop: 1 }} />{errText}</div>
          <button className="btn-ghost" style={{ marginTop: 10 }} onClick={() => setTick((t) => t + 1)}><Icon name="refresh" size={12} />{retryLabel}</button>
        </div>
      </Modal2>
    );
  }

  if (phase === "loading" || !est) {
    return (
      <Modal2 title={T2("upTitle")(reg.handle)} icon="refresh" onClose={onClose}>
        <div className="v2-card" style={{ padding: 18, textAlign: "center", color: "var(--dim)" }} role="status">{loadingText}</div>
      </Modal2>
    );
  }

  // phase === "ready"
  return (
    <Modal2 title={T2("upTitle")(reg.handle)} icon="refresh" onClose={onClose} wide>
      <p className="x2-msub">{T2("upSub")}</p>
      <div className="v2-card" style={{ padding: "4px 16px", boxShadow: "none" }}>
        <div className="fee-rows">
          <FeeRow icon="xLogo" title={T2("upXFee")} sub={T2("upNew")(newTweets) + " × $" + C.xPerTweet + " (X API)"} value={E.usd(est.xCost)} />
          {est.refresh ? (
            <FeeRow icon="cpu" title={T2("crLLMFee")} sub={T2("upRefreshYes")(C.updateThreshold) + " — " + T2("upRefreshHow")} value={E.usd(est.llmCost)} />
          ) : (
            <FeeRow icon="cpu" title={T2("crLLMFee")} sub={T2("upRefreshNo")(C.updateThreshold)} value="$0.00" />
          )}
          <FeeRow subrow title={T2("crSubtotal")} value={E.usd(est.subtotal)} />
          <FeeRow total title={T2("crTotal")} value={E.usd(est.total)} />
        </div>
        <div style={{ font: "400 10.5px var(--sans)", color: "var(--faint)", textAlign: "right", marginTop: 2 }}>{T2("feeTopupOnly")}</div>
      </div>
      <div className="rw-pitch">
        <span className="big">{C.rewardMult}×</span>
        <p>{T2("upReward")(C.rewardMult)}</p>
      </div>
      <div style={{ font: "400 11px/1.5 var(--sans)", color: "var(--faint)", background: "var(--card)", border: "1px solid var(--border)", borderRadius: "var(--r)", padding: "10px 12px", margin: "8px 0 12px" }}>{T2("upTakeover")}</div>
      {payErrText && (
        <div className="x2-note x2-danger" role="alert"><Icon name="shield" size={13} style={{ flex: "none", marginTop: 1 }} />{payErrText}</div>
      )}
      <button className="x2-primary" disabled={busy} onClick={pay}><Icon name="zap" size={14} />{busy ? submitting : T2("upPay")(E.usd(est.total))}</button>
      <div className="cr-bal"><span>{T2("crBalance")}</span><b>{E.usd(balTotal)}</b></div>
    </Modal2>
  );
}

Object.assign(window, { MarketPage, PersonaCard2, UpdateModal });
