// Page 4: 費用分析 — per-model donut, cache trend, token mix, forecast

function PageCost({ filters, density, chartStyle }) {
  const { BRANDS, DAILY_AGG, TOKEN_MIX, TODAY, DAYS } = window.MOCK;
  // 真實 per-model 統計從 cost.byModel endpoint 來；不再用 MODELS array + share 寫死
  const liveModels = (window.LIVE && window.LIVE.byModel && window.LIVE.byModel.models) || [];
  const byModel = liveModels.map((m) => ({
    id: m.model,
    provider: m.provider || (m.model && m.model.toLowerCase().includes('claude') ? 'anthropic' :
                              m.model && m.model.toLowerCase().includes('gpt') ? 'openai' : 'other'),
    cost: m.cost_usd || 0,
    requests: m.requests || 0,
    tokens: m.tokens || 0,
    // 後端尚未回 per-model price / latency / 14d trend，以下三項為 placeholder
    priceIn: null,
    priceOut: null,
    latency: null,
    trend: null,
  })).sort((a, b) => b.cost - a.cost);
  const totalCost = byModel.reduce((s, m) => s + m.cost, 0);
  const projectedMonth = DAYS > 0 ? totalCost * (30 / DAYS) : 0;
  const monthBudget = 18500;  // TODO: 接預算管理表

  const cacheTrend = TOKEN_MIX.map(d => d.cacheHit);
  const tokenMix = TOKEN_MIX.map(d => ({
    date: d.date,
    input: d.fresh,
    output: d.output,
    cache_read: d.cacheRead,
    cache_creation: d.cacheCreate,
  }));

  return (
    <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 14 }}>
      <PageHeader title="費用分析" subtitle="解釋帳單來源、預測月底支出" />

      <Card>
        <CardHeader title="月度預測" subtitle={`基於近 ${DAYS} 天的消耗速率推算`} />
        <ForecastBar projected={projectedMonth} budget={monthBudget} actual={totalCost} daysIn={DAYS} />
      </Card>

      <div style={{ display: 'grid', gridTemplateColumns: '320px 1fr', gap: 10 }}>
        <Card>
          <CardHeader title="各模型費用占比" subtitle="期間費用拆解" />
          <div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', gap: 16 }}>
            <Donut
              slices={byModel.map((m, i) => ({ value: m.cost, color: TOKENS.chart[i % TOKENS.chart.length] }))}
              size={130} thickness={20}
              centerLabel="總計" centerValue={fmtUSD(totalCost, 0)}
            />
            <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 6, fontSize: 11.5 }}>
              {byModel.map((m, i) => (
                <div key={m.id} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                  <span style={{ width: 8, height: 8, background: TOKENS.chart[i % TOKENS.chart.length], borderRadius: 2 }}></span>
                  <span style={{ color: '#17171A', fontFamily: 'JetBrains Mono', fontSize: 10.5, flex: 1 }}>{m.id}</span>
                  <span style={{ color: '#17171A', fontFamily: 'JetBrains Mono', fontWeight: 600 }}>{fmtUSD(m.cost, 0)}</span>
                  <span style={{ color: '#9098A3', fontFamily: 'JetBrains Mono', fontSize: 10, width: 36, textAlign: 'right' }}>{fmtPct(m.cost / totalCost, 0)}</span>
                </div>
              ))}
            </div>
          </div>
        </Card>

        <Card>
          <CardHeader title="模型使用對照" subtitle="費率、平均延遲、市占" />
          <ModelComparisonTable models={byModel} totalCost={totalCost} />
        </Card>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
        <Card>
          <CardHeader title="Cache 命中率趨勢" subtitle="目標 70% · 命中越高 = 越省"
            right={<span style={{ fontSize: 11, fontFamily: 'JetBrains Mono', color: cacheTrend[cacheTrend.length - 1] >= 0.7 ? '#15803D' : '#B45309', fontWeight: 600 }}>
              現在 {fmtPct(cacheTrend[cacheTrend.length - 1])}
            </span>} />
          <div style={{ padding: '12px 14px' }}>
            <CacheTrendChart data={cacheTrend} dates={DAILY_AGG.map(d => d.date)} />
          </div>
        </Card>

        <Card>
          <CardHeader title="Token 組成" subtitle="輸入 / 輸出 / Cache 讀取 / Cache 建立"
            right={<span style={{ fontSize: 11, color: '#B45309', fontWeight: 500 }}>↑ Cache 建立 4/29 飆高</span>} />
          <div style={{ padding: '12px 14px' }}>
            <TokenMixChart data={tokenMix} />
          </div>
        </Card>
      </div>

      <Card>
        <CardHeader title="Cache 命中率排行 Top 10" subtitle="點擊品牌可前往詳細頁討論優化方向" />
        <div style={{ padding: '12px 14px' }}>
          <CacheBrandTable brands={BRANDS} />
        </div>
      </Card>
    </div>
  );
}

function ForecastBar({ projected, budget, actual, daysIn }) {
  const projectedPct = (projected / budget) * 100;
  const actualPct = (actual / budget) * 100;
  const overBudget = projected > budget;

  return (
    <div style={{ padding: '14px 16px' }}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 16, marginBottom: 12 }}>
        <div>
          <div style={{ fontSize: 10.5, color: '#9098A3', fontFamily: 'JetBrains Mono', textTransform: 'uppercase', letterSpacing: '0.08em' }}>本月實際 ({daysIn}/30 天)</div>
          <div style={{ fontSize: 22, fontWeight: 600, color: '#17171A', fontFamily: 'JetBrains Mono', marginTop: 2 }}>{fmtUSD(actual, 0)}</div>
        </div>
        <div>
          <div style={{ fontSize: 10.5, color: '#9098A3', fontFamily: 'JetBrains Mono', textTransform: 'uppercase', letterSpacing: '0.08em' }}>月底預測</div>
          <div style={{ fontSize: 22, fontWeight: 600, fontFamily: 'JetBrains Mono', marginTop: 2, color: overBudget ? '#DC2626' : '#17171A' }}>{fmtUSD(projected, 0)}</div>
        </div>
        <div>
          <div style={{ fontSize: 10.5, color: '#9098A3', fontFamily: 'JetBrains Mono', textTransform: 'uppercase', letterSpacing: '0.08em' }}>月度預算</div>
          <div style={{ fontSize: 22, fontWeight: 600, color: '#5C6470', fontFamily: 'JetBrains Mono', marginTop: 2 }}>{fmtUSD(budget, 0)}</div>
        </div>
        <div style={{ marginLeft: 'auto', textAlign: 'right' }}>
          <div style={{ fontSize: 10.5, color: '#9098A3', fontFamily: 'JetBrains Mono' }}>使用率</div>
          <div style={{ fontSize: 22, fontWeight: 600, fontFamily: 'JetBrains Mono', color: overBudget ? '#DC2626' : projectedPct > 80 ? '#B45309' : '#15803D' }}>{projectedPct.toFixed(0)}%</div>
        </div>
      </div>

      <div style={{ position: 'relative', height: 30, background: '#F0F0EE', borderRadius: 5, overflow: 'hidden', border: '1px solid #E5E5E0' }}>
        <div style={{
          position: 'absolute', left: 0, top: 0, bottom: 0,
          width: Math.min(100, projectedPct) + '%',
          background: overBudget ? 'repeating-linear-gradient(135deg, #FCA5A5, #FCA5A5 6px, #FEE2E2 6px, #FEE2E2 12px)' : '#DBEAFE',
        }}></div>
        <div style={{
          position: 'absolute', left: 0, top: 0, bottom: 0,
          width: Math.min(100, actualPct) + '%',
          background: '#FFE600', borderRight: '1px solid #C8B400',
        }}></div>
        <div style={{
          position: 'absolute', left: '100%', top: -2, bottom: -2,
          width: 2, background: '#17171A',
        }}></div>
        <div style={{
          position: 'absolute', left: '100%', top: '100%', marginLeft: -25, marginTop: 4,
          fontSize: 10, color: '#5C6470', fontFamily: 'JetBrains Mono',
        }}>預算上限</div>
      </div>
      <div style={{ display: 'flex', gap: 16, marginTop: 18, fontSize: 11, color: '#5C6470' }}>
        <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}><span style={{ width: 12, height: 10, background: '#FFE600' }}></span>已實際支出</span>
        <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}><span style={{ width: 12, height: 10, background: '#DBEAFE' }}></span>線性預測</span>
        {overBudget && <span style={{ color: '#DC2626', fontWeight: 600 }}>⚠ 預期超出預算 {fmtUSD(projected - budget, 0)}</span>}
      </div>
    </div>
  );
}

function ModelComparisonTable({ models, totalCost }) {
  return (
    <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11.5 }}>
      <thead>
        <tr style={{ borderBottom: '1px solid #EEEEE9' }}>
          <Th>模型</Th>
          <Th style={{ textAlign: 'right' }}>輸入 $/M</Th>
          <Th style={{ textAlign: 'right' }}>輸出 $/M</Th>
          <Th style={{ textAlign: 'right' }}>平均延遲</Th>
          <Th style={{ textAlign: 'right' }}>使用占比</Th>
          <Th style={{ textAlign: 'right' }}>費用</Th>
          <Th style={{ textAlign: 'right' }}>請求數</Th>
        </tr>
      </thead>
      <tbody>
        {models.map((m, i) => (
          <tr key={m.id} style={{ borderBottom: '1px solid #EEEEE9', height: 32 }}>
            <td style={{ padding: '6px 12px' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                <span style={{ width: 6, height: 6, background: TOKENS.chart[i % TOKENS.chart.length], borderRadius: '50%' }}></span>
                <span style={{ color: '#17171A', fontFamily: 'JetBrains Mono', fontSize: 11 }}>{m.id}</span>
              </div>
            </td>
            <td className="mono" style={{ padding: '6px 12px', textAlign: 'right', color: '#9098A3' }} title="後端尚未回 LiteLLM 即時費率">{m.priceIn != null ? '$' + m.priceIn.toFixed(2) : '—'}</td>
            <td className="mono" style={{ padding: '6px 12px', textAlign: 'right', color: '#9098A3' }} title="後端尚未回 LiteLLM 即時費率">{m.priceOut != null ? '$' + m.priceOut.toFixed(2) : '—'}</td>
            <td className="mono" style={{ padding: '6px 12px', textAlign: 'right', color: '#9098A3' }} title="平均延遲尚未 instrument">{m.latency != null ? m.latency + 'ms' : '—'}</td>
            <td className="mono" style={{ padding: '6px 12px', textAlign: 'right', color: '#5C6470' }}>{totalCost > 0 ? fmtPct(m.cost / totalCost, 1) : '—'}</td>
            <td className="mono" style={{ padding: '6px 12px', textAlign: 'right', color: '#17171A', fontWeight: 600 }}>{fmtUSD(m.cost, m.cost < 10 ? 4 : 0)}</td>
            <td className="mono" style={{ padding: '6px 12px', textAlign: 'right', color: '#5C6470' }}>{fmtNum(m.requests || 0)}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

function CacheTrendChart({ data, dates }) {
  const w = 440, h = 180;
  const padL = 32, padR = 12, padT = 14, padB = 24;
  const innerW = w - padL - padR;
  const innerH = h - padT - padB;
  const target = 0.7;
  const max = 1;
  const stepX = innerW / (data.length - 1);

  const path = data.map((v, i) => {
    const x = padL + i * stepX;
    const y = padT + innerH - (v / max) * innerH;
    return (i === 0 ? 'M' : 'L') + x.toFixed(1) + ',' + y.toFixed(1);
  }).join(' ');

  const targetY = padT + innerH - (target / max) * innerH;

  return (
    <svg width={w} height={h} style={{ display: 'block' }}>
      {[0.25, 0.5, 0.75, 1].map(t => {
        const y = padT + innerH - t * innerH;
        return (
          <g key={t}>
            <line x1={padL} x2={w - padR} y1={y} y2={y} stroke="#EEEEE9" strokeDasharray="2 3" />
            <text x={padL - 6} y={y + 3} fontSize={10} fill="#9098A3" textAnchor="end" fontFamily="JetBrains Mono">{(t * 100).toFixed(0)}%</text>
          </g>
        );
      })}
      <line x1={padL} x2={w - padR} y1={targetY} y2={targetY} stroke="#15803D" strokeDasharray="4 3" strokeWidth={1.25} />
      <text x={w - padR - 4} y={targetY - 4} fontSize={10} fill="#15803D" textAnchor="end" fontFamily="JetBrains Mono" fontWeight={600}>目標 70%</text>

      <path d={path + ` L ${padL + (data.length - 1) * stepX},${padT + innerH} L ${padL},${padT + innerH} Z`} fill="#1D4ED8" fillOpacity={0.12} />
      <path d={path} stroke="#1D4ED8" strokeWidth={1.5} fill="none" />
      {data.map((v, i) => (
        <circle key={i} cx={padL + i * stepX} cy={padT + innerH - (v / max) * innerH} r={1.8} fill="#1D4ED8" />
      ))}

      {[0, Math.floor(data.length / 2), data.length - 1].map(i => (
        <text key={i} x={padL + i * stepX} y={h - 6} fontSize={10} fill="#9098A3" textAnchor="middle" fontFamily="JetBrains Mono">{dates[i].slice(5)}</text>
      ))}
    </svg>
  );
}

function TokenMixChart({ data }) {
  const w = 440, h = 180;
  const padL = 40, padR = 12, padT = 14, padB = 24;
  const innerW = w - padL - padR;
  const innerH = h - padT - padB;
  const totals = data.map(d => d.input + d.output + d.cache_read + d.cache_creation);
  const max = Math.max(...totals) * 1.05;
  const barW = innerW / data.length * 0.8;
  const stepX = innerW / data.length;

  const colors = { input: '#1D4ED8', output: '#15803D', cache_read: '#6D28D9', cache_creation: '#B45309' };
  const labels = { input: '輸入', output: '輸出', cache_read: 'Cache 讀', cache_creation: 'Cache 建' };

  return (
    <div>
      <svg width={w} height={h} style={{ display: 'block' }}>
        {[0.25, 0.5, 0.75, 1].map(t => {
          const y = padT + innerH - t * innerH;
          return (
            <g key={t}>
              <line x1={padL} x2={w - padR} y1={y} y2={y} stroke="#EEEEE9" strokeDasharray="2 3" />
              <text x={padL - 6} y={y + 3} fontSize={10} fill="#9098A3" textAnchor="end" fontFamily="JetBrains Mono">{fmtCompact(max * t)}</text>
            </g>
          );
        })}
        {data.map((d, i) => {
          const x = padL + i * stepX + (stepX - barW) / 2;
          let yAcc = padT + innerH;
          return ['cache_creation', 'cache_read', 'output', 'input'].map(k => {
            const h_ = (d[k] / max) * innerH;
            yAcc -= h_;
            return <rect key={i + k} x={x} y={yAcc} width={barW} height={h_} fill={colors[k]} fillOpacity={0.85} />;
          });
        })}
      </svg>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 12, fontSize: 10.5, marginTop: 4 }}>
        {Object.entries(labels).map(([k, l]) => (
          <span key={k} style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
            <span style={{ width: 8, height: 8, background: colors[k], borderRadius: 1 }}></span>
            <span style={{ color: '#5C6470' }}>{l}</span>
          </span>
        ))}
      </div>
    </div>
  );
}

function CacheBrandTable({ brands }) {
  const sorted = [...brands].sort((a, b) => a.cacheHit - b.cacheHit).slice(0, 10);
  return (
    <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 11.5 }}>
      <thead>
        <tr style={{ borderBottom: '1px solid #EEEEE9' }}>
          <Th style={{ width: 30, textAlign: 'right' }}>#</Th>
          <Th>品牌</Th>
          <Th style={{ textAlign: 'right' }}>對話數</Th>
          <Th style={{ textAlign: 'right' }}>Cache 命中</Th>
          <Th style={{ textAlign: 'right' }}>潛在節省</Th>
          <Th style={{ width: 200 }}>vs 目標 70%</Th>
        </tr>
      </thead>
      <tbody>
        {sorted.map((b, i) => {
          const gap = 0.7 - b.cacheHit;
          const savings = gap > 0 ? b.totalCost * gap * 0.85 : 0;
          return (
            <tr key={b.id} style={{ borderBottom: '1px solid #EEEEE9', height: 32 }}>
              <td style={{ padding: '6px 12px', color: '#9098A3', fontFamily: 'JetBrains Mono', textAlign: 'right' }}>{i + 1}</td>
              <td style={{ padding: '6px 12px' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <BrandThumb id={b.id} />
                  <span style={{ color: '#17171A', fontWeight: 500 }}>{b.name}</span>
                </div>
              </td>
              <td style={{ padding: '6px 12px', textAlign: 'right', fontFamily: 'JetBrains Mono', color: '#17171A' }}>{fmtNum(b.totalConvos)}</td>
              <td style={{ padding: '6px 12px', textAlign: 'right', fontFamily: 'JetBrains Mono', color: b.cacheHit < 0.5 ? '#DC2626' : '#B45309', fontWeight: 600 }}>{fmtPct(b.cacheHit)}</td>
              <td style={{ padding: '6px 12px', textAlign: 'right', fontFamily: 'JetBrains Mono', color: '#15803D', fontWeight: 600 }}>~{fmtUSD(savings, 0)}/月</td>
              <td style={{ padding: '6px 12px' }}>
                <div style={{ position: 'relative', height: 6, background: '#F0F0EE', borderRadius: 3, overflow: 'hidden' }}>
                  <div style={{
                    position: 'absolute', left: 0, top: 0, bottom: 0,
                    width: (b.cacheHit * 100) + '%',
                    background: b.cacheHit >= 0.7 ? '#15803D' : b.cacheHit >= 0.5 ? '#B45309' : '#DC2626',
                  }}></div>
                  <div style={{ position: 'absolute', left: '70%', top: -2, bottom: -2, width: 1, background: '#17171A' }}></div>
                </div>
              </td>
            </tr>
          );
        })}
      </tbody>
    </table>
  );
}

window.PageCost = PageCost;
