// 模型管理 — 按厂商分级 · 紧凑列表 · 接入真实 /api/providers + /api/credentials

// 按 ModelSpec 拼一个简短的价格标签（用于下拉 option 后缀 + 凭据行 chip）
function formatModelPrice(model) {
  if (!model) return "";
  const cur = model.currency === "USD" ? "$" : "¥";
  if (model.kind === "chat" || model.kind === "multimodal") {
    const ip = model.input_price, op = model.output_price;
    if (ip != null && op != null) {
      return `${cur}${ip}/${cur}${op} ·1M tok`;
    }
  }
  if (model.kind === "video_t2v" || model.kind === "video_i2v") {
    return `${cur}${model.price}/s`;
  }
  if (model.kind === "image") {
    return `${cur}${model.price}/张`;
  }
  if (model.kind === "asr") {
    return `${cur}${model.price}/min`;
  }
  return "";
}

const ModelsPage = () => {
  const [providers, setProviders]     = React.useState([]);   // [{key,label,kind,fields}]
  const [credentials, setCredentials] = React.useState([]);   // [{id,provider,name,api_key,...}]
  const [loading, setLoading]         = React.useState(true);
  const [error, setError]             = React.useState("");
  const [adding, setAdding]           = React.useState(null); // provider key under add
  const [form, setForm]               = React.useState({});
  const [saving, setSaving]           = React.useState(false);
  const [busyId, setBusyId]           = React.useState(0);
  const [openCatalog, setOpenCatalog] = React.useState({});   // {providerKey: true}

  // 厂商展示元数据（key 对应 PROVIDERS 的 key）
  const vendorMeta = {
    siliconflow:       { short: "硅", bg: "#5046E4" },
    gemini:            { short: "G",  bg: "#4285F4" },
    openai_compat:     { short: "OC", bg: "#10A37F" },
    openai_multimodal: { short: "OM", bg: "#10A37F" },
    kling:             { short: "可", bg: "#FF5043" },
    seedance:          { short: "豆", bg: "#1664FF" },
    minimax:           { short: "Mi", bg: "#3D7BFE" },
    runway:            { short: "R",  bg: "#7C3AED" },
    luma:              { short: "L",  bg: "#111111" },
    pika:              { short: "P",  bg: "#FF4D6D" },
    vidu:              { short: "V",  bg: "#7C3AED" },
    custom_api:        { short: "*",  bg: "#888888" },
    douyin_hub:        { short: "抖", bg: "#000000" },
    douyin_cookie:     { short: "C",  bg: "#111111" },
  };

  // 排序优先级：硅基流动 → 多模态 LLM → 视频 API → 数据源 → 其他
  const providerOrder = [
    "siliconflow", "gemini", "openai_multimodal", "openai_compat",
    "kling", "seedance", "minimax", "runway", "luma", "pika", "vidu", "custom_api",
    "douyin_hub", "douyin_cookie",
  ];

  // ─── 数据装载 ───
  React.useEffect(() => { reload(); }, []);

  async function reload() {
    setLoading(true); setError("");
    try {
      const [p, c] = await Promise.all([API.providers.list(), API.credentials.list()]);
      setProviders(p.items || []);
      setCredentials(c.items || []);
    } catch (e) {
      setError(String(e.message || e));
    } finally {
      setLoading(false);
    }
  }

  // ─── 操作 ───
  async function handleActivate(cred) {
    if (cred.is_active) return;
    setBusyId(cred.id);
    try {
      await API.credentials.activate(cred.id);
      await reload();
    } catch (e) { alert("激活失败：" + (e.message || e)); }
    finally { setBusyId(0); }
  }
  async function handleDelete(cred) {
    if (!confirm(`删除凭据「${cred.name}」？此操作不可撤销。`)) return;
    setBusyId(cred.id);
    try {
      await API.credentials.delete(cred.id);
      await reload();
    } catch (e) { alert("删除失败：" + (e.message || e)); }
    finally { setBusyId(0); }
  }
  async function handleTest(cred) {
    setBusyId(cred.id);
    try {
      const r = await API.credentials.test(cred.id);
      alert(`${r.ok ? "✓ 测试通过" : "✗ 测试失败"}\n${r.message || ""}${r.latency_ms ? ` (${r.latency_ms}ms)` : ""}`);
      await reload();
    } catch (e) { alert("测试失败：" + (e.message || e)); }
    finally { setBusyId(0); }
  }

  function startAdd(providerKey) {
    setAdding(providerKey);
    setForm({});
  }
  function cancelAdd() { setAdding(null); setForm({}); }

  async function submitAdd(spec) {
    const name = (form.name || "").trim();
    if (!name) { alert("请填写凭据名称"); return; }
    for (const f of spec.fields) {
      if (f.required && !form[f.key]) { alert(`「${f.label}」是必填字段`); return; }
    }
    setSaving(true);
    try {
      const body = { provider: spec.key, name };
      for (const f of spec.fields) {
        const v = form[f.key];
        if (v !== undefined && v !== "") body[f.key] = v;
      }
      await API.credentials.create(body);
      cancelAdd();
      await reload();
    } catch (e) {
      alert("添加失败：" + (e.message || e));
    } finally {
      setSaving(false);
    }
  }

  // ─── 分组 ───
  const credByProvider = {};
  for (const c of credentials) {
    if (!credByProvider[c.provider]) credByProvider[c.provider] = [];
    credByProvider[c.provider].push(c);
  }
  // 显示所有 providers，不论是否有凭据（"+ 添加" 永远可见）
  const providersSorted = [...providers].sort((a, b) => {
    const ai = providerOrder.indexOf(a.key); const bi = providerOrder.indexOf(b.key);
    return (ai < 0 ? 999 : ai) - (bi < 0 ? 999 : bi);
  });

  const totalCreds   = credentials.length;
  const totalActive  = credentials.filter(c => c.is_active).length;
  const totalVendors = providers.length;

  // provider key → models[] 反查表（用于在凭据行展示价格 chip）
  const modelsByProvider = React.useMemo(() => {
    const m = {};
    for (const p of providers) {
      m[p.key] = {};
      for (const md of (p.models || [])) m[p.key][md.id] = md;
    }
    return m;
  }, [providers]);

  // ─── 单行渲染 ───
  const credRow = (cred, idx) => {
    const isErr = cred.last_test_status === "error";
    const stCol  = isErr ? "pink" : (cred.is_active ? "green" : "fg-2");
    const stText = isErr ? "异常" : (cred.is_active ? "在线" : "待机");
    const isBusy = busyId === cred.id;
    const modelName = cred.extra && cred.extra.model_name;
    const modelSpec = modelName && modelsByProvider[cred.provider]
      ? modelsByProvider[cred.provider][modelName]
      : null;
    const priceLabel = formatModelPrice(modelSpec);

    return (
      <div key={cred.id} className="row" style={{
        padding: "9px 12px",
        borderTop: idx > 0 ? "1px solid var(--line-1)" : "none",
        gap: 10,
        alignItems: "center",
        opacity: isBusy ? 0.5 : (cred.is_active ? 1 : 0.78),
      }}>
        <span style={{ fontSize: 12.5, fontWeight: 500, color: "var(--fg-0)", whiteSpace: "nowrap" }}>{cred.name}</span>
        {modelName && (
          <span className="mono" style={{ fontSize: 9.5, color: "var(--fg-3)", padding: "1px 5px", background: "var(--bg-0)", borderRadius: 3, whiteSpace: "nowrap" }}>{modelName}</span>
        )}
        {priceLabel && (
          <span title={modelSpec.notes || ""} style={{
            fontSize: 9.5, color: "var(--cyan)", padding: "1px 5px",
            background: "color-mix(in oklch, var(--cyan) 12%, var(--bg-1))",
            border: "1px solid color-mix(in oklch, var(--cyan) 30%, transparent)",
            borderRadius: 3, whiteSpace: "nowrap", fontFamily: "ui-monospace, SF Mono, Menlo, monospace",
          }}>{priceLabel}</span>
        )}
        {cred.base_url && (
          <span className="mono" style={{ fontSize: 10, color: "var(--fg-3)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", maxWidth: 220 }} title={cred.base_url}>
            {cred.base_url.replace(/^https?:\/\//, "")}
          </span>
        )}
        <span style={{ flex: 1 }} />
        <span className="mono" style={{ fontSize: 10, color: "var(--fg-3)" }}>KEY · {cred.api_key || "未配置"}</span>
        <span className={`tag ${stCol === "green" ? "green" : stCol === "pink" ? "pink" : ""}`} style={{ fontSize: 10 }}>
          <span className="dot" style={{ background: `var(--${stCol})`, width: 4, height: 4, marginRight: 3 }} />{stText}
        </span>
        <div onClick={() => handleActivate(cred)} title={cred.is_active ? "已激活（同 provider 下唯一）" : "点击激活"} style={{
          width: 28, height: 15,
          background: cred.is_active ? "var(--cyan)" : "var(--bg-3)",
          borderRadius: 8, position: "relative",
          cursor: cred.is_active ? "default" : "pointer",
          flexShrink: 0,
        }}>
          <div style={{ position: "absolute", top: 1.5, [cred.is_active ? "right" : "left"]: 1.5, width: 12, height: 12, background: "white", borderRadius: "50%" }} />
        </div>
        <button className="btn sm ghost" onClick={() => handleTest(cred)} disabled={isBusy} title="测试连通性"><Icon name="zap" size={10} /></button>
        <button className="btn sm ghost" onClick={() => handleDelete(cred)} disabled={isBusy} title="删除"><Icon name="close" size={10} /></button>
      </div>
    );
  };

  // ─── 添加表单 ───
  const addForm = (spec) => (
    <div style={{ padding: 12, background: "var(--bg-0)", borderTop: "1px solid var(--line-1)", display: "flex", flexDirection: "column", gap: 8 }}>
      <div className="row" style={{ gap: 8, alignItems: "center" }}>
        <span style={{ fontSize: 11, color: "var(--fg-2)", width: 80, flexShrink: 0 }}>名称<span style={{ color: "var(--pink)" }}> *</span></span>
        <input
          placeholder={`如：${spec.label} 主账号`}
          value={form.name || ""}
          onChange={e => setForm({ ...form, name: e.target.value })}
          style={{ flex: 1, padding: "6px 10px", fontSize: 12, border: "1px solid var(--line-1)", borderRadius: 4, background: "white", color: "var(--fg-0)" }}
        />
      </div>
      {spec.fields.map(f => {
        const isModelDropdown = f.key === "model_name" && (spec.models || []).length > 0;
        return (
          <div key={f.key} className="row" style={{ gap: 8, alignItems: "center" }}>
            <span style={{ fontSize: 11, color: "var(--fg-2)", width: 80, flexShrink: 0 }}>
              {f.label}{f.required && <span style={{ color: "var(--pink)" }}> *</span>}
            </span>
            {isModelDropdown ? (
              <select
                value={form.__custom_model__ ? "__custom__" : (form[f.key] || "")}
                onChange={e => {
                  const v = e.target.value;
                  if (v === "__custom__") {
                    setForm({ ...form, [f.key]: "", __custom_model__: true });
                  } else {
                    setForm({ ...form, [f.key]: v, __custom_model__: false });
                  }
                }}
                style={{ flex: 1, padding: "6px 10px", fontSize: 12, border: "1px solid var(--line-1)", borderRadius: 4, background: "white", color: "var(--fg-0)" }}
              >
                <option value="">— 请选择模型 —</option>
                {spec.models.map(m => (
                  <option key={m.id} value={m.id}>
                    {m.label} · {formatModelPrice(m)}{m.notes ? ` · ${m.notes}` : ""}
                  </option>
                ))}
                <option value="__custom__">自定义（手动填写模型 id）</option>
              </select>
            ) : (
              <input
                placeholder={f.placeholder || ""}
                value={form[f.key] || ""}
                onChange={e => setForm({ ...form, [f.key]: e.target.value })}
                type={f.type === "secret" ? "password" : "text"}
                style={{ flex: 1, padding: "6px 10px", fontSize: 12, border: "1px solid var(--line-1)", borderRadius: 4, background: "white", color: "var(--fg-0)", fontFamily: f.type === "secret" ? "ui-monospace, SF Mono, Menlo, monospace" : "inherit" }}
              />
            )}
          </div>
        );
      })}
      {/* 自定义模型时露出一个 text input 让用户填模型 id */}
      {form.__custom_model__ && (spec.models || []).length > 0 && (
        <div className="row" style={{ gap: 8, alignItems: "center" }}>
          <span style={{ fontSize: 11, color: "var(--fg-2)", width: 80, flexShrink: 0 }}>自定义 id</span>
          <input
            placeholder="不在下拉里的模型 id，例如 gpt-5.5-preview-20260201"
            value={form.model_name || ""}
            onChange={e => setForm({ ...form, model_name: e.target.value })}
            style={{ flex: 1, padding: "6px 10px", fontSize: 12, border: "1px solid var(--line-1)", borderRadius: 4, background: "white", color: "var(--fg-0)" }}
          />
        </div>
      )}
      <div className="row" style={{ gap: 6, justifyContent: "flex-end", marginTop: 4 }}>
        <button className="btn sm ghost" onClick={cancelAdd} disabled={saving}>取消</button>
        <button className="btn sm primary" onClick={() => submitAdd(spec)} disabled={saving}>
          {saving ? "保存中…" : "保存并添加"}
        </button>
      </div>
    </div>
  );

  return (
    <>
      <Topbar crumbs={["系统", "模型管理"]} right={<>
        <span className="pill live">{totalVendors} 厂商 · {totalCreds} 凭据 · {totalActive} 已激活</span>
        <button className="btn ghost" onClick={reload} title="刷新"><Icon name="chart" size={12} />刷新</button>
      </>} />
      <div className="main-body">
        {/* 左：消耗 + 预算 + 调用约定 */}
        <div className="col scroll" style={{ width: 300, flexShrink: 0, padding: "14px 14px 20px", gap: 12, borderRight: "1px solid var(--line-soft)" }}>
          <div className="card" style={{ padding: 12 }}>
            <div className="kpi-l">今日消耗</div>
            <div className="row between" style={{ marginTop: 6, alignItems: "flex-end" }}>
              <div className="row gap-4" style={{ alignItems: "baseline" }}><span className="kpi-v">¥1,284</span><span className="u" style={{ fontSize: 11, color: "var(--fg-2)" }}>.42</span></div>
              <span className="delta up">▲ +12.4%</span>
            </div>
            <hr className="hr" style={{ margin: "10px 0" }} />
            <div className="col gap-8" style={{ fontSize: 10.5 }}>
              {[
                { l: "硅基流动", v: "¥820", pct: 64, col: "purple" },
                { l: "Gemini",   v: "¥210", pct: 16, col: "cyan" },
                { l: "可灵",     v: "¥156", pct: 12, col: "green" },
                { l: "豆包",     v: "¥98",  pct: 8,  col: "orange" },
              ].map((r, i) => (
                <div key={i} className="col gap-4">
                  <div className="row between">
                    <span style={{ color: "var(--fg-2)" }}>{r.l}</span>
                    <span className="mono" style={{ color: "var(--fg-0)" }}>{r.v}</span>
                  </div>
                  <div className="bar"><span style={{ width: `${r.pct}%`, background: `var(--${r.col})` }} /></div>
                </div>
              ))}
            </div>
          </div>

          <div className="card">
            <div className="card-hd"><span className="card-title">预算与告警</span></div>
            <div className="col" style={{ padding: 12, gap: 10 }}>
              <div className="col gap-4">
                <div className="row between" style={{ fontSize: 10.5 }}>
                  <span style={{ color: "var(--fg-2)" }}>日预算</span>
                  <span className="mono" style={{ color: "var(--fg-0)" }}>¥1,284 / ¥2,000</span>
                </div>
                <div className="bar"><span style={{ width: "64%", background: "var(--cyan)" }} /></div>
              </div>
              <div className="col gap-4">
                <div className="row between" style={{ fontSize: 10.5 }}>
                  <span style={{ color: "var(--fg-2)" }}>月预算</span>
                  <span className="mono" style={{ color: "var(--fg-0)" }}>¥28,412 / ¥50,000</span>
                </div>
                <div className="bar"><span style={{ width: "56%", background: "var(--purple)" }} /></div>
              </div>
            </div>
          </div>

          <div className="card" style={{ padding: 12, fontSize: 10.5, color: "var(--fg-3)", lineHeight: 1.6 }}>
            <div className="card-title" style={{ marginBottom: 6, fontSize: 11.5 }}>调用约定</div>
            <span>业务方调用时显式指定 <span className="mono" style={{ color: "var(--fg-2)" }}>provider + name</span>，系统不做自动 fallback。同一 provider 下只有 1 个凭据可被激活。</span>
          </div>
        </div>

        {/* 中：按厂商分组的紧凑列表 */}
        <div className="col grow scroll" style={{ padding: "14px 14px 20px", gap: 14, background: "var(--bg-0)" }}>
          {loading && (
            <div className="card" style={{ padding: 24, textAlign: "center", color: "var(--fg-3)", fontSize: 12 }}>载入中…</div>
          )}
          {error && (
            <div className="card" style={{ padding: 16, color: "var(--pink)", fontSize: 12 }}>
              <Icon name="bell" size={11} /> 数据载入失败：{error}
            </div>
          )}
          {!loading && providersSorted.map((spec) => {
            const meta = vendorMeta[spec.key] || { short: spec.label.slice(0, 1), bg: "#888" };
            const credsForVendor = credByProvider[spec.key] || [];
            const onlineCount = credsForVendor.filter(c => c.is_active).length;
            return (
              <div key={spec.key}>
                <div className="row between" style={{ marginBottom: 8, padding: "0 4px" }}>
                  <div className="row gap-8" style={{ alignItems: "center" }}>
                    <div style={{ width: 24, height: 24, borderRadius: 5, background: meta.bg, color: "white", fontWeight: 700, fontSize: 11, display: "flex", alignItems: "center", justifyContent: "center", letterSpacing: "-0.3px" }}>
                      {meta.short}
                    </div>
                    <span style={{ fontSize: 13.5, fontWeight: 600, color: "var(--fg-0)" }}>{spec.label}</span>
                    <span className="tag" style={{ fontSize: 10 }}>{spec.kind === "video_api" ? "视频 API" : spec.kind === "multimodal_llm" ? "多模态 LLM" : spec.kind === "datasource" ? "数据源" : spec.kind}</span>
                    <span style={{ fontSize: 10.5, color: "var(--fg-3)" }}>
                      {credsForVendor.length} 凭据{credsForVendor.length > 0 ? ` · ${onlineCount} 已激活` : ""}
                    </span>
                    {(spec.models || []).length > 0 && (
                      <>
                        <select
                          value=""
                          onChange={e => {
                            const v = e.target.value;
                            if (!v) return;
                            // 选模型 = 打开该 provider 的添加表单并预填 model_name
                            setAdding(spec.key);
                            setForm({ model_name: v, __custom_model__: false });
                          }}
                          title="模型筛选：选一个版本即开启添加表单并预填"
                          style={{
                            fontSize: 10.5, padding: "3px 6px",
                            border: "1px solid var(--line-1)", borderRadius: 4,
                            background: "var(--bg-1)", color: "var(--fg-2)",
                            fontFamily: "inherit", cursor: "pointer",
                          }}
                        >
                          <option value="">▾ 模型筛选 ({spec.models.length})</option>
                          {spec.models.map(m => (
                            <option key={m.id} value={m.id}>
                              {m.label} · {formatModelPrice(m)}
                            </option>
                          ))}
                        </select>
                        <button
                          className="btn sm ghost"
                          onClick={() => setOpenCatalog({ ...openCatalog, [spec.key]: !openCatalog[spec.key] })}
                          title="展开 / 收起价格目录"
                          style={{ fontSize: 10.5, padding: "2px 6px" }}
                        >
                          {openCatalog[spec.key] ? "收起目录" : "查看目录"}
                        </button>
                      </>
                    )}
                  </div>
                </div>
                {openCatalog[spec.key] && (spec.models || []).length > 0 && (
                  <div className="card" style={{ padding: 0, marginBottom: 6 }}>
                    {spec.models.map((m, mi) => (
                      <div key={m.id} className="row" style={{
                        padding: "6px 12px",
                        borderTop: mi > 0 ? "1px solid var(--line-1)" : "none",
                        gap: 10, alignItems: "center", fontSize: 11,
                      }}>
                        <span style={{ fontWeight: 500, color: "var(--fg-0)", minWidth: 180 }}>{m.label}</span>
                        <span className="mono" style={{ fontSize: 9.5, color: "var(--fg-3)" }}>{m.id}</span>
                        <span style={{ flex: 1 }} />
                        <span className="mono" style={{
                          fontSize: 10, color: "var(--cyan)", padding: "1px 6px",
                          background: "color-mix(in oklch, var(--cyan) 12%, var(--bg-1))",
                          borderRadius: 3,
                        }}>{formatModelPrice(m)}</span>
                        {m.notes && <span style={{ fontSize: 10, color: "var(--fg-3)" }}>{m.notes}</span>}
                      </div>
                    ))}
                  </div>
                )}
                <div className="card" style={{ padding: 0 }}>
                  {credsForVendor.map((c, idx) => credRow(c, idx))}
                  {credsForVendor.length === 0 && adding !== spec.key && (
                    <div style={{ padding: "9px 12px", fontSize: 11, color: "var(--fg-3)" }}>
                      （暂无凭据）
                    </div>
                  )}
                  {adding === spec.key ? addForm(spec) : (
                    <div onClick={() => startAdd(spec.key)} style={{
                      padding: "9px 12px",
                      borderTop: credsForVendor.length > 0 ? "1px solid var(--line-1)" : "none",
                      color: "var(--fg-3)",
                      fontSize: 11.5,
                      cursor: "pointer",
                      display: "flex",
                      alignItems: "center",
                      gap: 6,
                    }}>
                      <Icon name="plus" size={11} /> 添加 {spec.label} 凭据
                    </div>
                  )}
                </div>
              </div>
            );
          })}
        </div>
      </div>
    </>
  );
};

Object.assign(window, { ModelsPage });
