/* Robindex v2 — "Clone anyone on X": link input → itemized cost estimate →
   pay → distilling progress → live. Real API only:
   RXAPI.cloneEstimate / cloneCreate / cloneStatus / wallet.
   No RXS / useStore2 / hash / mock-setTimeout. */
const { useState: crS, useEffect: crE, useRef: crR } = React;

function parseHandle(s) {
  const m = String(s || "").trim().match(/(?:x|twitter)\.com\/(@?[A-Za-z0-9_]{2,15})/) || String(s || "").trim().match(/^@?([A-Za-z0-9_]{2,15})$/);
  return m ? m[1].replace("@", "") : null;
}
function fmtFollowers(n) {
  if (n == null) return "";
  if (typeof n === "string") return n;
  const num = Number(n) || 0;
  if (num >= 1000) return (num / 1000).toFixed(num >= 10000 ? 0 : 1) + "K";
  return String(num);
}
function yearOf(v) {
  if (!v) return "";
  const y = new Date(v).getFullYear();
  return isNaN(y) ? "" : String(y);
}

function CreatePage({ lang, onOpenPersona, onTopup }) {
  const { Icon, Avatar } = window.RXC;
  const E = window.RXE, C = E.cfg();
  const [url, setUrl] = crS("");
  const [phase, setPhase] = crS("idle"); // idle | analyzing | found | taken | distilling
  const [prof, setProf] = crS(null);     // { profile, estimate, quoteId, expiresAt }
  const [takenHandle, setTakenHandle] = crS(null);
  const [handle, setHandle] = crS(null); // distilling handle (drives status polling)
  const [status, setStatus] = crS(null); // latest cloneStatus result
  const [err, setErr] = crS(null);
  const [busy, setBusy] = crS(false);
  const [bal, setBal] = crS({ cash: 0, reward: 0 });
  const firedReady = crR(false); // guard: dispatch rx2:refresh once when cloneStatus first turns ready

  // display-only wallet balance (cash + reward). Payment stays server-authoritative.
  crE(() => {
    let cancelled = false;
    (async () => {
      try {
        const r = await window.RXAPI.wallet({ limit: 1 });
        if (cancelled) return;
        if (r && !r.error && r.balances) {
          setBal({
            cash: Number(r.balances.cash) || 0,
            reward: Number(r.balances.reward) || 0,
          });
        }
      } catch (_) {}
    })();
    return () => { cancelled = true; };
  }, []);

  // poll clone status every 5s while distilling; stop on ready/failed; clear on unmount
  crE(() => {
    if (phase !== "distilling" || !handle) return;
    let cancelled = false;
    let timer = null;
    const tick = async () => {
      if (cancelled) return;
      let s = null;
      try {
        s = await window.RXAPI.cloneStatus(handle);
      } catch (_) {
        s = { error: "network_error" };
      }
      if (cancelled) return;
      setStatus(s);
      if (s && s.ready) {
        if (!firedReady.current) {
          firedReady.current = true;
          window.dispatchEvent(new CustomEvent("rx2:refresh"));
        }
        return;                                  // success — stop
      }
      if (s && !s.ready && (s.state === "failed" || s.last_error)) return; // failed — stop
      timer = setTimeout(tick, 5000);
    };
    tick();
    return () => { cancelled = true; if (timer) clearTimeout(timer); };
  }, [phase, handle]);

  const analyze = async () => {
    const h = parseHandle(url);
    if (!h || phase === "analyzing") return;
    setPhase("analyzing");
    setErr(null);
    setProf(null);
    setTakenHandle(null);
    setBusy(false);
    try {
      const r = await window.RXAPI.cloneEstimate(h);
      if (r && r.error) { setErr(r.error); setPhase("idle"); return; }
      if (r.taken) { setTakenHandle(h); setPhase("taken"); return; }
      if (r.profile && r.estimate && r.quoteId) { setProf(r); setPhase("found"); return; }
      setErr("invalid_response");
      setPhase("idle");
    } catch (_) {
      setErr("network_error");
      setPhase("idle");
    }
  };

  const pay = async () => {
    if (!prof || !prof.quoteId || busy) return;
    setBusy(true);
    setErr(null);
    try {
      const r = await window.RXAPI.cloneCreate(prof.quoteId);
      if (r && r.error) {
        if (r.need != null) onTopup(Number(r.need) || 0);
        else setErr(r.error);
        setBusy(false);
        return;
      }
      if (r && r.ok) {
        window.dispatchEvent(new CustomEvent("rx2:refresh"));
        setBusy(false);
        setHandle(prof.profile.handle);
        setStatus(null);
        setPhase("distilling");
        return;
      }
      setErr("request_failed");
      setBusy(false);
    } catch (_) {
      setErr("network_error");
      setBusy(false);
    }
  };

  const errText = (code) => {
    const zh = lang === "zh";
    const m = {
      unauthorized: zh ? "未登录，请先登录" : "Not signed in",
      network_error: zh ? "网络错误，请重试" : "Network error, please retry",
      request_failed: zh ? "请求失败，请重试" : "Request failed, please retry",
      invalid_response: zh ? "服务端返回异常，请重试" : "Invalid server response, please retry",
      not_found: zh ? "找不到该账号" : "Account not found",
      rate_limited: zh ? "请求过于频繁，请稍后" : "Rate limited, please wait",
      account_banned: zh ? "账户已被冻结" : "Account is frozen",
      quote_expired: zh ? "报价已过期，请重新估算" : "Quote expired, please re-estimate",
    };
    return m[code] || (zh ? "操作失败，请重试" : "Operation failed, please retry");
  };

  const est = prof && prof.estimate;
  const p = prof && prof.profile;
  const balTotal = bal.cash + bal.reward;
  const analyzing = phase === "analyzing";

  return (
    <div className="v2-page" data-screen-label="create">
      <div className="v2-wrap narrow">
        <div className="cr-hero">
          <div className="kicker"><Icon name="bot" size={13} />ROBINDEX CLONE ENGINE</div>
          <h1>{T2("crTitle1")} <em>{T2("crTitle2")}</em></h1>
          <p>{T2("crSub")}</p>
          <div className="cr-input">
            <Icon name="xLogo" size={16} color="var(--faint)" style={{ alignSelf: "center" }} />
            <input value={url} onChange={(e) => setUrl(e.target.value)} placeholder={T2("crPlaceholder")}
              onKeyDown={(e) => { if (e.key === "Enter") analyze(); }} />
            <button className="go" disabled={!parseHandle(url) || analyzing} onClick={analyze}>
              {analyzing ? T2("crAnalyzing") : T2("crAnalyze")}
            </button>
          </div>
          <div className="cr-once"><Icon name="lock" size={11} />{T2("crOnce")}</div>
          {err && (
            <div className="x2-note x2-danger" role="alert" style={{ marginTop: 12, maxWidth: 560, marginLeft: "auto", marginRight: "auto" }}>
              <Icon name="shield" size={13} style={{ flex: "none", marginTop: 1 }} />{errText(err)}
            </div>
          )}
        </div>

        {phase === "taken" && takenHandle && (
          <div className="v2-card" style={{ padding: 18, display: "flex", alignItems: "center", gap: 12, marginTop: 18 }}>
            <div className="lg-ic"><Icon name="bot" size={16} color="var(--dim)" /></div>
            <div style={{ flex: 1 }}>
              <b style={{ font: "600 14px var(--head)", color: "var(--text)" }}>@{takenHandle}</b>
              <div style={{ font: "400 12px var(--sans)", color: "var(--faint)" }}>{T2("crTaken")}</div>
            </div>
          </div>
        )}

        {phase === "distilling" && handle && (
          <DistillPanel handle={handle} status={status} lang={lang} />
        )}
      </div>

      {phase === "found" && est && p && (
        <div className="v2-wrap" style={{ marginTop: 4 }}>
          <div className="cr-cols">
            <div className="v2-card est-card" data-screen-label="create-estimate">
              <div className="est-prof">
                <Avatar kol={{ display_name: p.name, handle: p.handle, avatar_url: p.avatarUrl || ("https://unavatar.io/x/" + p.handle), accent: "#5B9DFF" }} size={40} radius={11} />
                <div className="meta"><b>@{p.handle}</b><span>{fmtFollowers(p.followers)} · since {yearOf(p.createdAt)}</span></div>
                <div className="chips">
                  <div className="c"><b>{Number(est.tweets || 0).toLocaleString()}</b><span>{T2("crPosts")}</span></div>
                  <div className="c"><b>{Math.round(Number(est.corpusTok || 0) / 1000)}K</b><span>{T2("crCorpus")} tok</span></div>
                </div>
              </div>
              <div className="v2-sec" style={{ margin: "10px 0 2px" }}>{T2("crEstTitle")}</div>
              <div style={{ font: "400 12px var(--sans)", color: "var(--faint)", marginBottom: 4 }}>{T2("crEstSub")}</div>
              <div className="fee-rows">
                <FeeRow icon="xLogo" title={T2("crXFee")} sub={T2("crXFeeSub")(Number(est.tweets || 0), C.xPerTweet)} value={E.usd(est.xCost)} />
                <FeeRow icon="cpu" title={T2("crLLMFee")} sub={T2("crLLMFeeSub")(Number(est.slices || 0), Number(est.proCalls || 0)) + " · " + Math.round(Number(est.llmIn || 0) / 1000) + "K in / " + Math.round(Number(est.llmOut || 0) / 1000) + "K out"} value={E.usd(est.llmCost)} />
                <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 className="rw-pitch">
                <span className="big">{C.rewardMult}× ≤ {E.usd(est.rewardCap, 0)}</span>
                <p>{T2("crRewardBody")(C.perCallFee, C.rewardMult)}</p>
              </div>
              <button className="cr-pay" disabled={busy} onClick={pay}>
                <Icon name="zap" size={15} />{busy ? (lang === "zh" ? "提交中…" : "Submitting…") : T2("crPay")(E.usd(est.total))}
              </button>
              <div className="cr-bal"><span>{T2("crBalance")}</span><b>{E.usd(balTotal)}</b><span>· {T2("nonRefund")}</span></div>
            </div>
            <div className="v2-card pipe" data-screen-label="create-pipeline">
              <div className="v2-sec" style={{ margin: "0 0 6px" }}><Icon name="branch" size={12} />{T2("crPipeline")}</div>
              {[["1", T2("crStep1"), T2("crStep1b")], ["2", T2("crStep2"), T2("crStep2b")], ["3", T2("crStep3"), T2("crStep3b")], ["4", T2("crStep4"), T2("crStep4b")]].map(([n, b, p2]) => (
                <div className="pipe-step" key={n}>
                  <div className="pipe-n">{n}</div>
                  <div><b>{b}</b><p>{p2}</p></div>
                </div>
              ))}
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

function DistillPanel({ handle, status, lang }) {
  const { Icon } = window.RXC;
  const E = window.RXE, C = E.cfg();
  if (!handle) return null;
  const ready = !!(status && status.ready);
  const failed = !!(status && !status.ready && (status.state === "failed" || status.last_error));
  const pct = ready ? 100 : Math.max(0, Math.min(100, Math.floor(Number(status && status.progress_percent) || 0)));
  const tweets = Number(status && status.tweets_fetched) || 0;
  const stepsCount = Number(status && status.distill_steps) || 0;
  const stateLabel = (status && status.state) ? String(status.state)
    : (status && status.error) ? "error"
    : (status ? "queued" : "queued");
  const steps = [
    [8, "x.fetch_archive", tweets.toLocaleString() + " posts"],
    [22, "denoise.originals", "quotes/RTs dropped"],
    [40, "map.slice[1..n] → deepseek-v4-pro", "300K ctx each"],
    [74, "reduce.merge → deepseek-v4-pro", "weighted merge"],
    [90, "verify.citations + coverage", "code-checked"],
    [100, "persona.live", "indexed + routable"],
  ];
  return (
    <div className="v2-card dst-panel" style={{ marginTop: 22 }} data-screen-label="create-distilling">
      <div className="ring" style={{ "--p": pct }}><span>{pct}%</span></div>
      <h2>{ready ? T2("crSuccessTitle") : T2("crDistilling") + " @" + handle}</h2>
      <p>{ready ? T2("crRewardBody")(C.perCallFee, C.rewardMult) : T2("crDistillSub")}</p>
      <div style={{ font: "400 12px var(--sans)", color: "var(--faint)", margin: "8px 0 0" }}>
        {lang === "zh" ? "状态" : "State"}: <code style={{ font: "600 12px var(--mono)" }}>{stateLabel}</code>
        {tweets > 0 && <> · {tweets.toLocaleString()} {T2("crPosts")}</>}
        {stepsCount > 0 && <> · {stepsCount} {lang === "zh" ? "步" : "steps"}</>}
      </div>
      <div className="dst-log">
        {steps.map(([at, cmd, note]) => (
          <div key={cmd} className={pct >= at ? "ok" : pct >= at - 18 ? "run" : ""}>
            {pct >= at ? "✓" : pct >= at - 18 ? "▸" : "·"} {cmd} <span style={{ opacity: .6 }}>— {note}</span>
          </div>
        ))}
      </div>
      {failed && (
        <div className="x2-note x2-danger" role="alert" style={{ marginTop: 14 }}>
          <Icon name="shield" size={13} style={{ flex: "none", marginTop: 1 }} />
          {lang === "zh" ? "蒸馏失败" : "Distillation failed"}{status && status.last_error ? ": " + String(status.last_error) : ""}
        </div>
      )}
      {status && status.error && !failed && (
        <div className="x2-note x2-danger" role="alert" style={{ marginTop: 14 }}>
          <Icon name="shield" size={13} style={{ flex: "none", marginTop: 1 }} />
          {lang === "zh" ? "状态查询失败，正在重试…" : "Status query failed, retrying…"}
        </div>
      )}
      {ready && (
        <a
          className="btn-ghost"
          href={"https://x.com/intent/post?text=" + encodeURIComponent(T2("crShareBody")(handle) + "\n\nhttps://app.robindex.ai/k/" + encodeURIComponent(handle) + "?utm_source=create&utm_medium=share")}
          target="_blank"
          rel="noopener noreferrer"
          style={{ display: "inline-flex", alignItems: "center", gap: 6, marginTop: 14, textDecoration: "none" }}
          onClick={() => { try { if (window.RXA) window.RXA.track("creator_share_clicked", { source: "create_live" }); } catch (_) {} }}
        >
          <Icon name="xLogo" size={13} />{T2("crShareInvite")}
        </a>
      )}
    </div>
  );
}

Object.assign(window, { CreatePage, DistillPanel });
