/* MaiAgent Partner Portal — Credit 估算器（仿 utils.maiagent.ai 風格） */

const CALC_LLM_MODELS = [
  { id: 'gemini-3.1-flash-lite', name: 'Gemini 3.1 Flash Lite', inputCr: 0.25, outputCr: 1.5  },
  { id: 'gemini-2.5-flash',      name: 'Gemini 2.5 Flash',      inputCr: 0.3,  outputCr: 2.5  },
  { id: 'gemini-3-flash',        name: 'Gemini 3 Flash',         inputCr: 0.5,  outputCr: 3    },
  { id: 'gpt-4.1-mini',          name: 'GPT-4.1 Mini',           inputCr: 0.4,  outputCr: 1.6  },
  { id: 'llama3.3-70b',          name: 'Llama 3.3 70B',          inputCr: 0.72, outputCr: 0.72 },
  { id: 'claude-haiku-4.5',      name: 'Claude Haiku 4.5',       inputCr: 1,    outputCr: 5    },
  { id: 'deepseek-r1',           name: 'DeepSeek R1',            inputCr: 1.35, outputCr: 5.4  },
  { id: 'gpt-4.1',               name: 'GPT-4.1',                inputCr: 2,    outputCr: 8    },
  { id: 'gpt-5',                 name: 'GPT-5 (o3)',             inputCr: 1.25, outputCr: 10   },
  { id: 'gemini-2.5-pro',        name: 'Gemini 2.5 Pro',         inputCr: 1.25, outputCr: 10   },
  { id: 'mistral-large',         name: 'Mistral Large',          inputCr: 2,    outputCr: 6    },
  { id: 'grok-4.20',             name: 'Grok 4.20',              inputCr: 2,    outputCr: 6    },
  { id: 'gemini-3.1-pro',        name: 'Gemini 3.1 Pro',         inputCr: 2,    outputCr: 12   },
  { id: 'claude-sonnet-4.5',     name: 'Claude Sonnet 4.5',      inputCr: 3,    outputCr: 15   },
  { id: 'gpt-5.4',               name: 'GPT-5.4',                inputCr: 2.5,  outputCr: 15   },
  { id: 'claude-opus-4.6',       name: 'Claude Opus 4.6',        inputCr: 5,    outputCr: 25   },
];

const CALC_EMBED_MODELS = [
  { id: 'embed-multilingual-v3',  name: 'Embed Multilingual v3 (Bedrock)', creditsPerKToken: 0.1  },
  { id: 'embed-v4.0',             name: 'Embed v4.0 (Cohere)',             creditsPerKToken: 0.12 },
  { id: 'text-embedding-3-large', name: 'text-embedding-3-large (OpenAI)', creditsPerKToken: 0.13 },
];

const CALC_PLANS = [
  { id: 'starter',    name: 'Starter',    monthlyCredits: 1000,     monthlyPrice: 0,     addOnPer10k: null },
  { id: 'growth',     name: 'Growth',     monthlyCredits: 500000,   monthlyPrice: 9000,  addOnPer10k: 180  },
  { id: 'pro',        name: 'Pro',        monthlyCredits: 5000000,  monthlyPrice: 30000, addOnPer10k: 120  },
  { id: 'enterprise', name: 'Enterprise', monthlyCredits: 10000000, monthlyPrice: 50000, addOnPer10k: 100  },
];

const GPU_MODELS = [
  { id: 'gemma-4-26b',  name: 'Gemma 4 26B (vLLM)',  tpsPerGpu: 8 },
  { id: 'gemma-4-31b',  name: 'Gemma 4 31B (vLLM)',  tpsPerGpu: 6 },
  { id: 'qwen-3.5-27b', name: 'Qwen 3.5 27B (vLLM)', tpsPerGpu: 7 },
  { id: 'gpt-oss-120b', name: 'GPT-OSS 120B (vLLM)', tpsPerGpu: 3 },
];

var _calcSeq = 0;
const calcId = () => ++_calcSeq;

const mkAssistant = () => ({
  id: calcId(), name: '', modelId: 'claude-haiku-4.5',
  dailyConv: 100, turns: 4, inputTok: 500, outputTok: 300, queryTok: 200,
  useKB: true, useRerank: false,
});

const mkLlmCall = () => ({
  id: calcId(), name: '', modelId: 'gpt-4.1-mini',
  inputTok: 500, outputTok: 300, dailyCalls: 1000,
});

const fmtCr  = n => Math.round(n).toLocaleString();
const fmtNTD = n => 'NT$ ' + Math.round(n).toLocaleString();

const compute = (assistants, kb, llmCalls) => {
  const aItems = assistants.map(a => {
    const m = CALC_LLM_MODELS.find(x => x.id === a.modelId) || CALC_LLM_MODELS[0];
    const turns = a.dailyConv * a.turns;
    const inputCr  = turns * a.inputTok  / 1000 * m.inputCr;
    const outputCr = turns * a.outputTok / 1000 * m.outputCr;
    const kbCr = a.useKB ? a.dailyConv * a.turns * (a.queryTok / 1000 * 0.13 + (a.useRerank ? 2 : 0)) : 0;
    const daily = inputCr + outputCr + kbCr;
    return { id: a.id, name: a.name || `AI 助理 ${a.id}`, modelName: m.name, daily, monthly: daily * 30 };
  });

  const embed = CALC_EMBED_MODELS.find(m => m.id === kb.embedModelId) || CALC_EMBED_MODELS[0];
  const overlapRatio = kb.chunkSize > 0 ? kb.chunkOverlap / kb.chunkSize : 0;
  const chunks = kb.enabled && kb.totalPages > 0
    ? Math.ceil(kb.totalPages * kb.avgTokensPerPage / (kb.chunkSize * (1 - overlapRatio)))
    : 0;
  const oneTimeCr = chunks * kb.chunkSize / 1000 * embed.creditsPerKToken;
  const storageMb = chunks * kb.chunkSize * 2.5 / 1024 / 1024;
  const storageCr = storageMb * 0.24;

  const llmItems = llmCalls.map(c => {
    const m = CALC_LLM_MODELS.find(x => x.id === c.modelId) || CALC_LLM_MODELS[0];
    const daily = c.dailyCalls * (c.inputTok / 1000 * m.inputCr + c.outputTok / 1000 * m.outputCr);
    return { id: c.id, name: c.name || `LLM 呼叫 ${c.id}`, daily, monthly: daily * 30 };
  });

  const totalMonthly = aItems.reduce((s, a) => s + a.monthly, 0)
    + llmItems.reduce((s, c) => s + c.monthly, 0)
    + storageCr;
  const plan = CALC_PLANS.find(p => p.monthlyCredits >= totalMonthly) || CALC_PLANS[CALC_PLANS.length - 1];
  const deficit = Math.max(0, totalMonthly - plan.monthlyCredits);
  const addOnCost = deficit > 0 && plan.addOnPer10k ? Math.ceil(deficit / 10000) * plan.addOnPer10k : 0;

  return { aItems, llmItems, oneTimeCr, storageMb, storageCr, totalMonthly, plan,
           surplus: Math.max(0, plan.monthlyCredits - totalMonthly), deficit, addOnCost,
           totalMonthlyCost: plan.monthlyPrice + addOnCost };
};

// ─── design tokens ─────────────────────────────────────────────────────────
const C = {
  card:    { background: '#fff', borderRadius: 12, border: '1px solid #E5E7EB', boxShadow: '0 1px 3px rgba(0,0,0,0.06)' },
  label:   { fontSize: 11, fontWeight: 700, color: '#9CA3AF', textTransform: 'uppercase', letterSpacing: '0.06em' },
  num:     { fontWeight: 700, fontVariantNumeric: 'tabular-nums' },
  input:   { width: '100%', border: '2px solid #E5E7EB', borderRadius: 8, padding: '7px 12px', fontSize: 13,
             fontFamily: 'inherit', outline: 'none', background: 'white', transition: 'border-color 0.15s' },
  select:  { width: '100%', border: '2px solid #E5E7EB', borderRadius: 8, padding: '7px 10px', fontSize: 13,
             fontFamily: 'inherit', outline: 'none', background: 'white', transition: 'border-color 0.15s', cursor: 'pointer' },
};

// ─── NumField ───────────────────────────────────────────────────────────────
const NumField = ({ label, value, onChange, step = 1, min = 0, accent = '#3B82F6', hint }) => {
  const [focused, setFocused] = React.useState(false);
  return (
    <div>
      <div style={{ ...C.label, marginBottom: 5 }}>{label}</div>
      <input
        type="number" value={value} min={min} step={step}
        onChange={e => onChange(Math.max(min, Number(e.target.value) || 0))}
        onFocus={() => setFocused(true)}
        onBlur={() => setFocused(false)}
        style={{ ...C.input, borderColor: focused ? accent : '#E5E7EB' }}
      />
      {hint && <div style={{ fontSize: 11, color: '#9CA3AF', marginTop: 3 }}>{hint}</div>}
    </div>
  );
};

// ─── SelectField ────────────────────────────────────────────────────────────
const SelectField = ({ label, value, onChange, options, accent = '#3B82F6' }) => {
  const [focused, setFocused] = React.useState(false);
  return (
    <div>
      <div style={{ ...C.label, marginBottom: 5 }}>{label}</div>
      <select
        value={value} onChange={e => onChange(e.target.value)}
        onFocus={() => setFocused(true)} onBlur={() => setFocused(false)}
        style={{ ...C.select, borderColor: focused ? accent : '#E5E7EB' }}
      >
        {options.map(o => <option key={o.value} value={o.value}>{o.label}</option>)}
      </select>
    </div>
  );
};

// ─── SectionCard ────────────────────────────────────────────────────────────
const SectionCard = ({ accentColor = '#3B82F6', icon, title, sub, action, children }) => (
  <div style={{ ...C.card, overflow: 'hidden' }}>
    <div style={{ borderLeft: `4px solid ${accentColor}`, padding: '16px 20px', borderBottom: '1px solid #F3F4F6' }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <Icon name={icon} size={16} style={{ color: accentColor }} />
          <span style={{ fontWeight: 700, fontSize: 14, color: '#111827' }}>{title}</span>
        </div>
        {action}
      </div>
      {sub && <div style={{ fontSize: 12, color: '#9CA3AF', marginTop: 3, paddingLeft: 24 }}>{sub}</div>}
    </div>
    <div style={{ padding: '16px 20px' }}>{children}</div>
  </div>
);

// ─── AssistantCard ──────────────────────────────────────────────────────────
const AssistantCard = ({ a, onChange, onRemove, lang }) => {
  const zh = lang === 'zh';
  const set = (k, v) => onChange({ ...a, [k]: v });
  const accent = '#3B82F6';

  return (
    <div style={{ border: '1px solid #E5E7EB', borderRadius: 10, overflow: 'hidden', background: '#FAFAFA' }}>
      {/* assistant header */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '10px 14px',
                    background: '#EFF6FF', borderBottom: '1px solid #DBEAFE' }}>
        <Icon name="sparkles" size={14} style={{ color: accent, flexShrink: 0 }} />
        <input
          value={a.name} onChange={e => set('name', e.target.value)}
          placeholder={zh ? '助理名稱（選填）' : 'Assistant name (optional)'}
          style={{ flex: 1, border: 'none', outline: 'none', fontSize: 13, fontWeight: 600,
                   color: '#1D4ED8', background: 'transparent', fontFamily: 'inherit' }}
        />
        <button onClick={onRemove}
          style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#93C5FD',
                   display: 'flex', padding: 2, borderRadius: 4 }}>
          <Icon name="x-circle" size={14} />
        </button>
      </div>

      {/* assistant fields */}
      <div style={{ padding: '14px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <div style={{ gridColumn: '1 / -1' }}>
          <SelectField label="LLM 模型" value={a.modelId} accent={accent}
            onChange={v => set('modelId', v)}
            options={CALC_LLM_MODELS.map(m => ({ value: m.id, label: `${m.name}  (in ${m.inputCr} / out ${m.outputCr} cr/K)` }))}
          />
        </div>
        <NumField label={zh ? '每日對話次數' : 'Daily Conversations'} value={a.dailyConv} step={10} accent={accent} onChange={v => set('dailyConv', v)} />
        <NumField label={zh ? '每次對話來回數' : 'Turns / Conversation'} value={a.turns} step={1} accent={accent} onChange={v => set('turns', v)} />
        <NumField label={zh ? 'Input tokens / 回' : 'Input Tokens / Turn'} value={a.inputTok} step={100} accent={accent} onChange={v => set('inputTok', v)} />
        <NumField label={zh ? 'Output tokens / 回' : 'Output Tokens / Turn'} value={a.outputTok} step={100} accent={accent} onChange={v => set('outputTok', v)} />
        {a.useKB && (
          <NumField label={zh ? 'Query tokens（KB）' : 'Query Tokens (KB)'} value={a.queryTok}
            step={50} accent="#F97316" onChange={v => set('queryTok', v)}
            hint={zh ? '知識庫提問長度' : 'Knowledge base query length'}
          />
        )}

        {/* checkboxes */}
        <div style={{ gridColumn: '1 / -1', display: 'flex', gap: 20, paddingTop: 6 }}>
          <label style={{ display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer', fontSize: 12.5, color: '#4B5563' }}>
            <input type="checkbox" checked={a.useKB} onChange={e => set('useKB', e.target.checked)}
              style={{ accentColor: accent, width: 14, height: 14 }} />
            {zh ? '知識庫檢索' : 'Knowledge Base'}
          </label>
          <label style={{ display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer', fontSize: 12.5, color: a.useKB ? '#4B5563' : '#D1D5DB' }}>
            <input type="checkbox" checked={a.useRerank} disabled={!a.useKB}
              onChange={e => set('useRerank', e.target.checked)}
              style={{ accentColor: accent, width: 14, height: 14 }} />
            Rerank
          </label>
        </div>
      </div>
    </div>
  );
};

// ─── LlmCallCard ────────────────────────────────────────────────────────────
const LlmCallCard = ({ c, onChange, onRemove, lang }) => {
  const zh = lang === 'zh';
  const set = (k, v) => onChange({ ...c, [k]: v });
  const accent = '#8B5CF6';

  return (
    <div style={{ border: '1px solid #E5E7EB', borderRadius: 10, overflow: 'hidden', background: '#FAFAFA' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '10px 14px',
                    background: '#F5F3FF', borderBottom: '1px solid #EDE9FE' }}>
        <Icon name="zap" size={14} style={{ color: accent, flexShrink: 0 }} />
        <input
          value={c.name} onChange={e => set('name', e.target.value)}
          placeholder={zh ? '呼叫名稱（選填）' : 'Call name (optional)'}
          style={{ flex: 1, border: 'none', outline: 'none', fontSize: 13, fontWeight: 600,
                   color: '#6D28D9', background: 'transparent', fontFamily: 'inherit' }}
        />
        <button onClick={onRemove}
          style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#C4B5FD', display: 'flex', padding: 2 }}>
          <Icon name="x-circle" size={14} />
        </button>
      </div>
      <div style={{ padding: 14, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <div style={{ gridColumn: '1 / -1' }}>
          <SelectField label="LLM 模型" value={c.modelId} accent={accent}
            onChange={v => set('modelId', v)}
            options={CALC_LLM_MODELS.map(m => ({ value: m.id, label: `${m.name}  (in ${m.inputCr} / out ${m.outputCr} cr/K)` }))}
          />
        </div>
        <NumField label={zh ? 'Input tokens / 次' : 'Input Tokens / Call'} value={c.inputTok} step={100} accent={accent} onChange={v => set('inputTok', v)} />
        <NumField label={zh ? 'Output tokens / 次' : 'Output Tokens / Call'} value={c.outputTok} step={100} accent={accent} onChange={v => set('outputTok', v)} />
        <div style={{ gridColumn: '1 / -1' }}>
          <NumField label={zh ? '每日呼叫次數' : 'Daily Calls'} value={c.dailyCalls} step={100} accent={accent} onChange={v => set('dailyCalls', v)} />
        </div>
      </div>
    </div>
  );
};

// ─── PlanBar ────────────────────────────────────────────────────────────────
const PlanBar = ({ plan, totalMonthly, isRec }) => {
  const pct = plan.monthlyCredits > 0 ? Math.min(100, (totalMonthly / plan.monthlyCredits) * 100) : 0;
  return (
    <div style={{
      padding: '10px 12px', borderRadius: 8,
      border: `1.5px solid ${isRec ? '#BFDBFE' : '#F3F4F6'}`,
      background: isRec ? '#EFF6FF' : '#FAFAFA',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
          {isRec && <span style={{ background: '#3B82F6', color: 'white', fontSize: 9, fontWeight: 700,
                            padding: '1px 5px', borderRadius: 3, letterSpacing: '0.05em' }}>推薦</span>}
          <span style={{ fontWeight: 700, fontSize: 13, color: isRec ? '#1D4ED8' : '#374151' }}>{plan.name}</span>
        </div>
        <span style={{ fontSize: 11.5, color: '#6B7280', ...C.num }}>
          {fmtCr(plan.monthlyCredits)} cr/月
        </span>
      </div>
      <div style={{ height: 5, borderRadius: 99, background: '#E5E7EB', overflow: 'hidden' }}>
        <div style={{ height: '100%', width: pct + '%', borderRadius: 99,
                      background: isRec ? '#3B82F6' : '#D1D5DB', transition: 'width 0.5s' }} />
      </div>
      {isRec && (
        <div style={{ fontSize: 11, color: '#2563EB', marginTop: 5, ...C.num }}>
          剩餘 {fmtCr(Math.max(0, plan.monthlyCredits - totalMonthly))} cr（{Math.round(Math.max(0, plan.monthlyCredits - totalMonthly) / plan.monthlyCredits * 100)}% 餘裕）
        </div>
      )}
    </div>
  );
};

// ─── CalculatorPage ─────────────────────────────────────────────────────────
const CalculatorPage = ({ t, lang }) => {
  const zh = lang === 'zh';
  const [activeTab, setActiveTab] = React.useState('credit');
  const [assistants, setAssistants] = React.useState([mkAssistant()]);
  const [llmCalls,   setLlmCalls]   = React.useState([]);
  const [kb, setKb] = React.useState({
    enabled: true, totalPages: 500, avgTokensPerPage: 400,
    chunkSize: 512, chunkOverlap: 64, embedModelId: 'embed-multilingual-v3',
  });

  const res = React.useMemo(() => compute(assistants, kb, llmCalls), [assistants, kb, llmCalls]);

  const TABS = [
    { id: 'credit',  icon: 'wallet',  zh: 'Credit 估算',  en: 'Credit Estimator' },
    { id: 'license', icon: 'users',   zh: '套數估算器',    en: 'License Count'    },
    { id: 'gpu',     icon: 'layers',  zh: 'GPU 容量估算', en: 'GPU Capacity'      },
  ];

  return (
    <div className="page">
      {/* Page header */}
      <div className="page-header">
        <div className="page-header__title">
          <div className="page-header__eyebrow">{zh ? '銷售工具' : 'Sales Toolkit'}</div>
          <h1>{zh ? 'MaiAgent 估算器' : 'MaiAgent Estimator'}</h1>
          <div className="page-header__sub">
            {zh ? '估算 AI 助理導入的 Credit 費用與方案推薦' : 'Estimate credit costs and get plan recommendations'}
          </div>
        </div>
        <a href="https://utils.maiagent.ai/" target="_blank" rel="noopener noreferrer" style={{ textDecoration: 'none' }}>
          <Btn variant="ghost" icon="external">{zh ? '完整版' : 'Full Version'}</Btn>
        </a>
      </div>

      {/* Tabs */}
      <div style={{ display: 'flex', gap: 4, marginBottom: 20,
                    background: '#F3F4F6', padding: 4, borderRadius: 10, width: 'fit-content' }}>
        {TABS.map(tb => {
          const active = activeTab === tb.id;
          return (
            <button key={tb.id} onClick={() => setActiveTab(tb.id)} style={{
              display: 'flex', alignItems: 'center', gap: 6,
              padding: '7px 14px', borderRadius: 8, border: 'none', cursor: 'pointer',
              fontWeight: 600, fontSize: 13, transition: 'all 0.15s', fontFamily: 'inherit',
              background: active ? 'white' : 'transparent',
              color: active ? '#1D4ED8' : '#6B7280',
              boxShadow: active ? '0 1px 3px rgba(0,0,0,0.1)' : 'none',
            }}>
              <Icon name={tb.icon} size={14} />
              {zh ? tb.zh : tb.en}
            </button>
          );
        })}
      </div>

      {/* ── Credit Estimator ── */}
      {activeTab === 'credit' && (
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 340px', gap: 20, alignItems: 'start' }}>

          {/* Left: inputs */}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>

            {/* AI 助理 */}
            <SectionCard accentColor="#3B82F6" icon="sparkles"
              title={zh ? 'AI 助理（含知識庫檢索）' : 'AI Assistants (with KB)'}
              sub={zh ? '每個助理的 LLM 模型與對話用量設定' : 'LLM model and conversation settings per assistant'}
              action={
                <button onClick={() => setAssistants(p => [...p, mkAssistant()])} style={{
                  display: 'flex', alignItems: 'center', gap: 5, padding: '5px 10px',
                  border: '1.5px solid #BFDBFE', borderRadius: 7, background: '#EFF6FF',
                  color: '#2563EB', fontSize: 12, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit',
                }}>
                  <Icon name="plus" size={12} /> {zh ? '新增助理' : 'Add'}
                </button>
              }
            >
              <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                {assistants.map(a => (
                  <AssistantCard key={a.id} a={a} lang={lang}
                    onChange={next => setAssistants(p => p.map(x => x.id === a.id ? next : x))}
                    onRemove={() => setAssistants(p => p.filter(x => x.id !== a.id))}
                  />
                ))}
                {assistants.length === 0 && (
                  <div style={{ textAlign: 'center', padding: '24px 0', color: '#9CA3AF', fontSize: 13,
                                border: '1.5px dashed #E5E7EB', borderRadius: 8 }}>
                    {zh ? '點擊右上角新增 AI 助理' : 'Click Add to create an assistant'}
                  </div>
                )}
              </div>
            </SectionCard>

            {/* 知識庫建置 */}
            <SectionCard accentColor="#F97316" icon="book-open"
              title={zh ? '知識庫建置（一次性費用）' : 'Knowledge Base Setup (One-time)'}
              sub={zh ? '建立向量資料庫的 Embedding 費用與持續儲存成本' : 'Embedding cost to build vector DB + monthly storage'}
              action={
                <label style={{ display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer', fontSize: 12.5, color: '#6B7280' }}>
                  <input type="checkbox" checked={kb.enabled}
                    onChange={e => setKb(p => ({ ...p, enabled: e.target.checked }))}
                    style={{ accentColor: '#F97316', width: 14, height: 14 }} />
                  {zh ? '啟用' : 'Enable'}
                </label>
              }
            >
              {kb.enabled ? (
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
                  <NumField label={zh ? '文件總頁數' : 'Total Pages'} value={kb.totalPages}
                    step={100} accent="#F97316" onChange={v => setKb(p => ({ ...p, totalPages: v }))} />
                  <NumField label={zh ? '平均 Tokens / 頁' : 'Avg Tokens / Page'} value={kb.avgTokensPerPage}
                    step={50} accent="#F97316" onChange={v => setKb(p => ({ ...p, avgTokensPerPage: v }))} />
                  <NumField label="Chunk Size (tokens)" value={kb.chunkSize}
                    step={64} min={64} accent="#F97316" onChange={v => setKb(p => ({ ...p, chunkSize: v }))} />
                  <NumField label="Chunk Overlap (tokens)" value={kb.chunkOverlap}
                    step={16} accent="#F97316"
                    onChange={v => setKb(p => ({ ...p, chunkOverlap: Math.min(v, p.chunkSize - 1) }))} />
                  <div style={{ gridColumn: '1 / -1' }}>
                    <SelectField label={zh ? 'Embedding 模型' : 'Embedding Model'} value={kb.embedModelId}
                      accent="#F97316"
                      onChange={v => setKb(p => ({ ...p, embedModelId: v }))}
                      options={CALC_EMBED_MODELS.map(m => ({
                        value: m.id, label: `${m.name} — ${m.creditsPerKToken} cr/K tokens`,
                      }))}
                    />
                  </div>
                  {/* KB summary row */}
                  <div style={{ gridColumn: '1 / -1', display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)',
                                gap: 10, background: '#FFF7ED', border: '1px solid #FED7AA',
                                borderRadius: 8, padding: '10px 14px' }}>
                    {[
                      { label: zh ? '建置費用（一次性）' : 'Setup (one-time)', value: fmtCr(Math.round(res.oneTimeCr)) + ' cr', color: '#EA580C' },
                      { label: zh ? '向量儲存（每月）' : 'Storage / month', value: fmtCr(Math.round(res.storageCr)) + ' cr', color: '#78716C' },
                      { label: zh ? '資料量估算' : 'Est. size', value: res.storageMb.toFixed(1) + ' MB', color: '#78716C' },
                    ].map(item => (
                      <div key={item.label}>
                        <div style={{ ...C.label, marginBottom: 2 }}>{item.label}</div>
                        <div style={{ fontWeight: 700, fontSize: 15, color: item.color, ...C.num }}>{item.value}</div>
                      </div>
                    ))}
                  </div>
                </div>
              ) : (
                <div style={{ color: '#9CA3AF', fontSize: 13, padding: '8px 0' }}>
                  {zh ? '已停用知識庫費用估算' : 'Knowledge base cost disabled'}
                </div>
              )}
            </SectionCard>

            {/* 純 LLM 呼叫 */}
            <SectionCard accentColor="#8B5CF6" icon="zap"
              title={zh ? '純 LLM 呼叫（不含知識庫）' : 'Pure LLM Calls (no KB)'}
              sub={zh ? '後台自動化、摘要、分類等直接 API 呼叫' : 'Automation, summarization, classification, etc.'}
              action={
                <button onClick={() => setLlmCalls(p => [...p, mkLlmCall()])} style={{
                  display: 'flex', alignItems: 'center', gap: 5, padding: '5px 10px',
                  border: '1.5px solid #DDD6FE', borderRadius: 7, background: '#F5F3FF',
                  color: '#7C3AED', fontSize: 12, fontWeight: 600, cursor: 'pointer', fontFamily: 'inherit',
                }}>
                  <Icon name="plus" size={12} /> {zh ? '新增呼叫' : 'Add'}
                </button>
              }
            >
              <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                {llmCalls.map(c => (
                  <LlmCallCard key={c.id} c={c} lang={lang}
                    onChange={next => setLlmCalls(p => p.map(x => x.id === c.id ? next : x))}
                    onRemove={() => setLlmCalls(p => p.filter(x => x.id !== c.id))}
                  />
                ))}
                {llmCalls.length === 0 && (
                  <div style={{ textAlign: 'center', padding: '20px 0', color: '#9CA3AF', fontSize: 13,
                                border: '1.5px dashed #E5E7EB', borderRadius: 8 }}>
                    {zh ? '無純 LLM 呼叫' : 'Click Add to create a call'}
                  </div>
                )}
              </div>
            </SectionCard>
          </div>

          {/* Right: results panel */}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14, position: 'sticky', top: 20 }}>

            {/* Monthly total */}
            <div style={{ ...C.card, padding: '20px' }}>
              <div style={{ ...C.label, marginBottom: 8 }}>{zh ? '預估每月 Credit 用量' : 'Est. Monthly Credits'}</div>
              <div style={{ fontSize: 36, fontWeight: 800, color: '#2563EB', lineHeight: 1, ...C.num }}>
                {fmtCr(Math.round(res.totalMonthly))}
              </div>
              <div style={{ fontSize: 12, color: '#9CA3AF', marginTop: 2 }}>credits / 月</div>

              {res.oneTimeCr > 0 && (
                <div style={{ marginTop: 12, paddingTop: 12, borderTop: '1px solid #F3F4F6',
                              display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                  <span style={{ fontSize: 12, color: '#9CA3AF' }}>{zh ? '一次性建置' : 'One-time setup'}</span>
                  <span style={{ fontWeight: 700, fontSize: 14, color: '#EA580C', ...C.num }}>
                    +{fmtCr(Math.round(res.oneTimeCr))} cr
                  </span>
                </div>
              )}
            </div>

            {/* Breakdown */}
            {res.totalMonthly > 0 && (
              <div style={{ ...C.card, padding: '16px 20px' }}>
                <div style={{ ...C.label, marginBottom: 10 }}>{zh ? '費用明細（每月）' : 'Monthly Breakdown'}</div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 7 }}>
                  {res.aItems.map(a => (
                    <div key={a.id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', fontSize: 12.5 }}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 5, minWidth: 0 }}>
                        <div style={{ width: 6, height: 6, borderRadius: 2, background: '#3B82F6', flexShrink: 0 }} />
                        <span style={{ color: '#4B5563', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{a.name}</span>
                      </div>
                      <span style={{ fontWeight: 600, color: '#111827', flexShrink: 0, marginLeft: 8, ...C.num }}>{fmtCr(Math.round(a.monthly))} cr</span>
                    </div>
                  ))}
                  {res.llmItems.map(c => (
                    <div key={c.id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', fontSize: 12.5 }}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
                        <div style={{ width: 6, height: 6, borderRadius: 2, background: '#8B5CF6', flexShrink: 0 }} />
                        <span style={{ color: '#4B5563' }}>{c.name}</span>
                      </div>
                      <span style={{ fontWeight: 600, color: '#111827', flexShrink: 0, marginLeft: 8, ...C.num }}>{fmtCr(Math.round(c.monthly))} cr</span>
                    </div>
                  ))}
                  {res.storageCr > 0 && (
                    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', fontSize: 12.5 }}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
                        <div style={{ width: 6, height: 6, borderRadius: 2, background: '#F97316', flexShrink: 0 }} />
                        <span style={{ color: '#4B5563' }}>{zh ? '向量儲存' : 'Vector Storage'}</span>
                      </div>
                      <span style={{ fontWeight: 600, color: '#111827', flexShrink: 0, marginLeft: 8, ...C.num }}>{fmtCr(Math.round(res.storageCr))} cr</span>
                    </div>
                  )}
                  <div style={{ borderTop: '1px solid #F3F4F6', paddingTop: 7,
                                display: 'flex', justifyContent: 'space-between', fontSize: 13 }}>
                    <span style={{ fontWeight: 700, color: '#111827' }}>Total</span>
                    <span style={{ fontWeight: 800, color: '#2563EB', ...C.num }}>{fmtCr(Math.round(res.totalMonthly))} cr</span>
                  </div>
                </div>
              </div>
            )}

            {/* Plan recommendation */}
            <div style={{ ...C.card, padding: '16px 20px' }}>
              <div style={{ ...C.label, marginBottom: 10 }}>{zh ? '方案推薦' : 'Plan Recommendation'}</div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                {CALC_PLANS.map(p => (
                  <PlanBar key={p.id} plan={p} totalMonthly={res.totalMonthly} isRec={p.id === res.plan.id} />
                ))}
              </div>
            </div>

            {/* Cost summary */}
            <div style={{ ...C.card, overflow: 'hidden' }}>
              <div style={{ padding: '14px 16px', borderBottom: '1px solid #F3F4F6' }}>
                <div style={{ ...C.label, marginBottom: 0 }}>{zh ? '費用估算' : 'Cost Estimate'}</div>
              </div>
              <div style={{ padding: '14px 16px', display: 'flex', flexDirection: 'column', gap: 8 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13 }}>
                  <span style={{ color: '#6B7280' }}>{res.plan.name} {zh ? '方案月費' : 'Plan Fee'}</span>
                  <span style={{ fontWeight: 600, ...C.num }}>{fmtNTD(res.plan.monthlyPrice)}</span>
                </div>
                {res.addOnCost > 0 && (
                  <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13 }}>
                    <span style={{ color: '#6B7280' }}>{zh ? '加購 Credits' : 'Add-on Credits'}</span>
                    <span style={{ fontWeight: 600, color: '#EA580C', ...C.num }}>+{fmtNTD(res.addOnCost)}</span>
                  </div>
                )}
              </div>
              <div style={{ padding: '12px 16px', background: '#EFF6FF', borderTop: '2px solid #BFDBFE',
                            display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <span style={{ fontWeight: 700, fontSize: 14, color: '#1E40AF' }}>{zh ? '總月支出' : 'Total / Month'}</span>
                <span style={{ fontWeight: 800, fontSize: 20, color: '#2563EB', ...C.num }}>{fmtNTD(res.totalMonthlyCost)}</span>
              </div>
              {res.oneTimeCr > 0 && (
                <div style={{ padding: '8px 16px', background: '#FFF7ED', borderTop: '1px solid #FED7AA',
                              fontSize: 11.5, color: '#92400E' }}>
                  {zh
                    ? `＋ 首月一次性建置 ${fmtCr(Math.round(res.oneTimeCr))} credits（從首月額度扣除）`
                    : `+ One-time ${fmtCr(Math.round(res.oneTimeCr))} credits deducted from first month`}
                </div>
              )}
            </div>

            <div style={{ fontSize: 11.5, color: '#9CA3AF', lineHeight: 1.6, padding: '0 2px' }}>
              {zh ? '以上為估算值，實際費用依用量與方案條款為準。' : 'Estimates only. Actual costs subject to usage and terms.'}
              {' '}
              <a href="https://utils.maiagent.ai/" target="_blank" rel="noopener noreferrer" style={{ color: '#3B82F6' }}>
                {zh ? '使用完整估算器 →' : 'Open full estimator →'}
              </a>
            </div>
          </div>
        </div>
      )}

      {/* ── License Count ── */}
      {activeTab === 'license' && <LicenseEstimator lang={lang} />}

      {/* ── GPU Capacity ── */}
      {activeTab === 'gpu' && <GpuEstimator lang={lang} />}
    </div>
  );
};

// ─── LicenseEstimator ────────────────────────────────────────────────────────
const LicenseEstimator = ({ lang }) => {
  const zh = lang === 'zh';
  const [accounts, setAccounts] = React.useState(0);
  const [cu,       setCu]       = React.useState(0);

  const byAccounts = accounts > 0 ? Math.ceil(accounts / 500) : 0;
  const byCu       = cu > 0       ? Math.ceil(cu / 100)       : 0;
  const recommended = Math.max(byAccounts, byCu);
  const determinant = byAccounts > byCu ? 'accounts' : byCu > byAccounts ? 'cu' : byAccounts > 0 ? 'equal' : 'none';

  const Tag = ({ active, color }) => active ? (
    <span style={{ fontSize: 10, fontWeight: 700, padding: '2px 6px', borderRadius: 4, marginLeft: 6,
                   background: color + '20', color }}>
      {zh ? '決定值' : 'Deciding'}
    </span>
  ) : null;

  return (
    <div style={{ maxWidth: 680 }}>
      <div style={{ marginBottom: 20 }}>
        <h2 style={{ fontSize: 22, fontWeight: 800, color: '#111827', margin: 0 }}>
          {zh ? 'MaiAgent 套數估算器' : 'MaiAgent License Count Estimator'}
        </h2>
        <p style={{ fontSize: 14, color: '#6B7280', marginTop: 6 }}>
          {zh
            ? '輸入帳號數與同時使用人數，估算需要購買幾套 MaiAgent 授權'
            : 'Enter account count and concurrent users to estimate required MaiAgent licenses'}
        </p>
      </div>

      {/* Input cards */}
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginBottom: 20 }}>
        {/* Accounts card */}
        <div style={{ borderRadius: 12, border: '1px solid #BFDBFE', background: '#EFF6FF', padding: '20px' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
            <div style={{ width: 28, height: 28, borderRadius: 8, background: '#DBEAFE',
                          display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <Icon name="users" size={14} style={{ color: '#2563EB' }} />
            </div>
            <span style={{ fontWeight: 700, fontSize: 13, color: '#1E40AF' }}>
              {zh ? '帳號數' : 'Total Accounts'}
            </span>
          </div>
          <p style={{ fontSize: 12, color: '#3B82F6', lineHeight: 1.6, marginBottom: 12 }}>
            {zh
              ? '需要在 MaiAgent 系統中建立帳號的使用者總數。包含所有會登入平台的員工、管理員或外部使用者，無論使用頻率高低。'
              : 'Total users who need accounts in MaiAgent, including all employees, admins, and external users regardless of usage frequency.'}
          </p>
          <p style={{ fontSize: 11, fontWeight: 700, color: '#2563EB', marginBottom: 10 }}>
            {zh ? '每 500 個帳號 = 1 套' : 'Every 500 accounts = 1 license'}
          </p>
          <NumField label={zh ? '帳號數' : 'Account Count'} value={accounts} step={100} min={0}
            accent="#2563EB" onChange={setAccounts} />
          {byAccounts > 0 && (
            <p style={{ fontSize: 12, color: '#2563EB', marginTop: 8, ...C.num }}>
              → {zh ? `需要 ${byAccounts} 套（${accounts} ÷ 500 無條件進位）` : `${byAccounts} license(s) needed (${accounts} ÷ 500, ceil)`}
            </p>
          )}
        </div>

        {/* CU card */}
        <div style={{ borderRadius: 12, border: '1px solid #DDD6FE', background: '#F5F3FF', padding: '20px' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
            <div style={{ width: 28, height: 28, borderRadius: 8, background: '#EDE9FE',
                          display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <Icon name="zap" size={14} style={{ color: '#7C3AED' }} />
            </div>
            <span style={{ fontWeight: 700, fontSize: 13, color: '#6D28D9' }}>
              {zh ? '同時使用者 CU（人）' : 'Concurrent Users (CU)'}
            </span>
          </div>
          <p style={{ fontSize: 12, color: '#8B5CF6', lineHeight: 1.6, marginBottom: 12 }}>
            {zh
              ? '在業務尖峰時段，預計同時與 AI 助理進行對話的最高人數。反映系統需要承載的即時負載，決定運算資源的規格。'
              : 'Peak number of users simultaneously chatting with AI assistants. Determines the compute resources required.'}
          </p>
          <p style={{ fontSize: 11, fontWeight: 700, color: '#7C3AED', marginBottom: 10 }}>
            {zh ? '每 100 CU = 1 套' : 'Every 100 CU = 1 license'}
          </p>
          <NumField label={zh ? '同時使用者 CU' : 'Concurrent Users'} value={cu} step={10} min={0}
            accent="#7C3AED" onChange={setCu} />
          {byCu > 0 && (
            <p style={{ fontSize: 12, color: '#7C3AED', marginTop: 8, ...C.num }}>
              → {zh ? `需要 ${byCu} 套（${cu} ÷ 100 無條件進位）` : `${byCu} license(s) needed (${cu} ÷ 100, ceil)`}
            </p>
          )}
        </div>
      </div>

      {/* Result */}
      {recommended > 0 ? (
        <div style={{ ...C.card, overflow: 'hidden' }}>
          <div style={{ padding: '16px 20px', background: '#F0FDF4', borderBottom: '1px solid #BBF7D0',
                        display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
            <span style={{ fontWeight: 700, fontSize: 14, color: '#166534' }}>
              {zh ? '建議購買套數' : 'Recommended License Count'}
            </span>
          </div>
          <div style={{ padding: '20px', display: 'flex', alignItems: 'center', gap: 32 }}>
            <div>
              <div style={{ fontSize: 56, fontWeight: 800, color: '#16A34A', lineHeight: 1, ...C.num }}>{recommended}</div>
              <div style={{ fontSize: 16, fontWeight: 700, color: '#15803D', marginTop: 2 }}>{zh ? '套' : 'license(s)'}</div>
            </div>
            <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 10 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13 }}>
                <div style={{ width: 10, height: 10, borderRadius: 3, flexShrink: 0,
                              background: determinant === 'accounts' || determinant === 'equal' ? '#2563EB' : '#D1D5DB' }} />
                <span style={{ color: determinant === 'accounts' || determinant === 'equal' ? '#1E40AF' : '#9CA3AF' }}>
                  {zh ? `帳號數試算：${byAccounts} 套` : `By accounts: ${byAccounts}`}
                </span>
                <Tag active={determinant === 'accounts' || determinant === 'equal'} color="#2563EB" />
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13 }}>
                <div style={{ width: 10, height: 10, borderRadius: 3, flexShrink: 0,
                              background: determinant === 'cu' || determinant === 'equal' ? '#7C3AED' : '#D1D5DB' }} />
                <span style={{ color: determinant === 'cu' || determinant === 'equal' ? '#6D28D9' : '#9CA3AF' }}>
                  {zh ? `CU 試算：${byCu} 套` : `By CU: ${byCu}`}
                </span>
                <Tag active={determinant === 'cu' || determinant === 'equal'} color="#7C3AED" />
              </div>
              {determinant === 'equal' && byAccounts > 0 && (
                <p style={{ fontSize: 11.5, color: '#6B7280', marginTop: 4 }}>
                  {zh ? '帳號數與 CU 試算結果相同' : 'Both calculations yield the same result'}
                </p>
              )}
            </div>
          </div>
          <div style={{ padding: '10px 20px', background: '#F9FAFB', borderTop: '1px solid #F3F4F6',
                        fontSize: 12, color: '#9CA3AF' }}>
            {zh
              ? '取帳號數試算與 CU 試算的較大值。詳細報價請聯繫 MaiAgent 業務。'
              : 'Takes the larger of account-based and CU-based calculations. Contact MaiAgent sales for detailed pricing.'}
          </div>
        </div>
      ) : (
        <div style={{ ...C.card, padding: '32px', textAlign: 'center' }}>
          <Icon name="users" size={40} style={{ color: '#E5E7EB', margin: '0 auto 12px' }} />
          <p style={{ color: '#9CA3AF', fontSize: 14 }}>
            {zh ? '請輸入帳號數或 CU 以計算套數' : 'Enter account count or CU to calculate'}
          </p>
        </div>
      )}
    </div>
  );
};

// ─── GpuEstimator ────────────────────────────────────────────────────────────
const GpuEstimator = ({ lang }) => {
  const zh = lang === 'zh';
  const [users,  setUsers]  = React.useState(100);
  const [qpm,    setQpm]    = React.useState(2);
  const [modelId, setModelId] = React.useState('gemma-4-26b');

  const model = GPU_MODELS.find(m => m.id === modelId) || GPU_MODELS[0];
  const reqPerMin = users * qpm;
  const tps = reqPerMin / 60 * 300;
  const gpus = Math.max(model.id === 'gpt-oss-120b' ? 4 : 1, Math.ceil(tps / (model.tpsPerGpu * 300)));

  return (
    <div style={{ maxWidth: 680 }}>
      <SectionCard accentColor="#0EA5E9" icon="layers"
        title={zh ? 'GPU 規模估算（地端部署）' : 'GPU Capacity (On-premise)'}
        sub={zh ? '壓測口徑：1 分鐘內同時上線，每人 1–2 個問答' : 'Stress baseline: peak concurrent users, 1–2 Q&As each'}
      >
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14, marginBottom: 16 }}>
          <NumField label={zh ? '同時上線人數' : 'Concurrent Users'} value={users}
            step={10} accent="#0EA5E9" onChange={setUsers} />
          <NumField label={zh ? '每人每分鐘問答數' : 'Queries / Min / User'} value={qpm}
            step={1} min={1} accent="#0EA5E9" onChange={setQpm} />
          <div style={{ gridColumn: '1 / -1' }}>
            <SelectField label={zh ? 'LLM 模型（vLLM）' : 'LLM Model (vLLM)'} value={modelId}
              accent="#0EA5E9" onChange={setModelId}
              options={GPU_MODELS.map(m => ({ value: m.id, label: m.name }))}
            />
          </div>
        </div>

        {/* Result row */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12,
                      background: '#F0F9FF', border: '1px solid #BAE6FD', borderRadius: 10, padding: '16px 20px' }}>
          {[
            { label: zh ? '總請求 / 分鐘' : 'Total Req / Min', value: reqPerMin.toFixed(0), color: '#0369A1' },
            { label: zh ? '估算 TPS' : 'Est. TPS', value: tps.toFixed(0), color: '#0369A1' },
            { label: zh ? '建議 GPU 卡數' : 'Recommended GPUs', value: gpus + (zh ? ' 張' : ''), color: '#0EA5E9', large: true },
          ].map(item => (
            <div key={item.label}>
              <div style={{ ...C.label, marginBottom: 4, color: '#0EA5E9' }}>{item.label}</div>
              <div style={{ fontWeight: 800, fontSize: item.large ? 32 : 22, color: item.color, ...C.num, lineHeight: 1 }}>
                {item.value}
              </div>
            </div>
          ))}
        </div>

        <div style={{ marginTop: 12, fontSize: 12, color: '#9CA3AF', lineHeight: 1.7 }}>
          {zh ? '假設：KV cache fp8 量化 · 平均每答 ~300 tokens · 同卡輔助模型事件驅動，不影響主力 TPS。' : 'Assumptions: KV cache fp8 · avg ~300 tokens/response · auxiliary model shares GPU, event-driven.'}
        </div>
      </SectionCard>
    </div>
  );
};
