import { useEffect, useMemo, useState } from "react";
import { Coins, RefreshCw, Wallet, Cpu, Receipt, Activity } from "lucide-react";
import { myUsage, type MyUsage, type UsageDay } from "../lib/api";
import { Card, Panel, EmptyState, cn } from "../ui";

// 桌面端「用量」= 用户自己租户的计量观测：积分余额 + 消耗趋势 + 最近消耗。
// 数据来自 /api/v1/me/usage（面向用户口径，只看自己租户）。积分/金额为微单位（÷1e6）。

const MICRO = 1_000_000;
const credits = (m: number) => (m / MICRO).toLocaleString("zh-CN", { maximumFractionDigits: 2 });
const money = (m: number) => (m / MICRO).toLocaleString("zh-CN", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
const int = (n: number) => n.toLocaleString("zh-CN");
const mmdd = (s: string) => `${s.slice(4, 6)}-${s.slice(6, 8)}`;

function ymd(d: Date): string {
  return `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, "0")}${String(d.getDate()).padStart(2, "0")}`;
}
function fillDays(trend: UsageDay[], days: number): UsageDay[] {
  const by = new Map(trend.map((d) => [d.day, d]));
  const out: UsageDay[] = [];
  const now = new Date();
  for (let i = days - 1; i >= 0; i--) {
    const d = new Date(now);
    d.setDate(now.getDate() - i);
    const key = ymd(d);
    out.push(by.get(key) ?? { day: key, total_tok: 0, credits_micro: 0, cost_micros: 0, task_count: 0 });
  }
  return out;
}

export function UsageView() {
  const [days, setDays] = useState(30);
  const [data, setData] = useState<MyUsage | null>(null);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);
  const [err, setErr] = useState("");

  const load = async () => {
    setRefreshing(true);
    try {
      setData(await myUsage(days));
      setErr("");
    } catch (e) {
      setErr((e as Error).message);
    } finally {
      setLoading(false);
      setRefreshing(false);
    }
  };
  useEffect(() => {
    void load();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [days]);

  const series = useMemo(() => (data ? fillDays(data.trend, days) : []), [data, days]);

  if (loading) return <div className="p-6 text-sm text-slate-500">加载用量中…</div>;
  if (err) return <div className="p-6 text-sm text-danger">用量加载失败：{err}</div>;
  if (!data) return null;

  const bal = data.balance_micro / MICRO;
  const empty = data.credit_enforce && bal <= 0;
  const low = !empty && bal > 0 && bal < 10;
  const t = data.totals;

  return (
    <div className="flex h-full flex-col gap-4 overflow-y-auto p-5">
      {/* 顶栏 */}
      <div className="flex items-center justify-between">
        <div>
          <h2 className="text-lg font-semibold text-slate-100">用量 & 计费</h2>
          <p className="text-xs text-slate-500">
            {mmdd(data.from)} ~ {mmdd(data.to)} · 我的租户口径
          </p>
        </div>
        <div className="flex items-center gap-2">
          <div className="flex overflow-hidden rounded-md border border-line text-xs">
            {[7, 30].map((d) => (
              <button
                key={d}
                onClick={() => setDays(d)}
                className={cn("px-3 py-1.5", days === d ? "bg-brand text-white" : "bg-ink-850 text-slate-400 hover:text-slate-200")}
              >
                近 {d} 天
              </button>
            ))}
          </div>
          <button
            onClick={() => void load()}
            disabled={refreshing}
            className="flex items-center gap-1 rounded-md border border-line bg-ink-850 px-2.5 py-1.5 text-xs text-slate-400 hover:text-slate-200 disabled:opacity-40"
          >
            <RefreshCw className={cn("h-3.5 w-3.5", refreshing && "animate-spin")} />
            刷新
          </button>
        </div>
      </div>

      {/* 余额 hero + KPI */}
      <div className="grid grid-cols-1 gap-4 lg:grid-cols-4">
        <Card className={cn("p-4", empty ? "border-danger/40" : low ? "border-warn/40" : "")}>
          <div className="flex items-center gap-1.5 text-xs text-slate-500">
            <Wallet className="h-3.5 w-3.5" /> 积分余额
          </div>
          <div className={cn("mt-1 text-3xl font-semibold tabular-nums", empty ? "text-danger" : low ? "text-warn" : "text-brand")}>
            {empty ? "余额不足" : credits(data.balance_micro)}
          </div>
          <div className="mt-1 text-[11px] text-slate-500">
            {data.credit_enforce ? "余额≤0 将无法提交任务" : "当前不拦截，仅计量"}
          </div>
        </Card>
        <Metric icon={Coins} label="积分消耗" value={credits(t.credits_micro)} sub={`区间合计 · ${int(t.task_count)} 次运行`} accent="text-accent" />
        <Metric icon={Cpu} label="Token 用量" value={int(t.total_tok)} sub="prompt + completion（估算）" accent="text-slate-100" />
        <Metric icon={Receipt} label="估算成本" value={money(t.cost_micros)} sub="按定价折算（配置币种）" accent="text-slate-100" />
      </div>

      {/* 消耗趋势 */}
      <Panel title="积分消耗趋势" icon={Activity} className="min-h-[200px]">
        <TrendBars series={series} />
      </Panel>

      {/* 最近消耗 */}
      <Panel title="最近消耗" icon={Coins} className="min-h-[160px]">
        {data.recent.length === 0 ? (
          <EmptyState icon={Coins} title="暂无消耗记录" />
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b border-line text-left text-[11px] uppercase tracking-wide text-slate-500">
                  <th className="py-2 pr-3 font-medium">任务</th>
                  <th className="pr-3 font-medium">模型</th>
                  <th className="pr-3 text-right font-medium">Token</th>
                  <th className="pr-3 text-right font-medium">积分</th>
                  <th className="text-right font-medium">成本</th>
                </tr>
              </thead>
              <tbody>
                {data.recent.map((r) => (
                  <tr key={r.task_id} className="border-b border-line/50 last:border-0">
                    <td className="py-2 pr-3 font-mono text-xs text-slate-300">{r.task_id}</td>
                    <td className="pr-3 text-xs text-slate-400">{r.model || "—"}</td>
                    <td className="pr-3 text-right tabular-nums text-slate-400">{int(r.total_tok)}</td>
                    <td className="pr-3 text-right tabular-nums text-accent">{credits(r.credits_micro)}</td>
                    <td className="text-right tabular-nums text-slate-400">{money(r.cost_micros)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </Panel>
    </div>
  );
}

function Metric({ icon: Icon, label, value, sub, accent }: { icon: typeof Coins; label: string; value: string; sub: string; accent: string }) {
  return (
    <Card className="p-4">
      <div className="flex items-center gap-1.5 text-xs text-slate-500">
        <Icon className="h-3.5 w-3.5" /> {label}
      </div>
      <div className={cn("mt-1 text-2xl font-semibold tabular-nums", accent)}>{value}</div>
      <div className="mt-1 text-[11px] text-slate-500">{sub}</div>
    </Card>
  );
}

function TrendBars({ series }: { series: UsageDay[] }) {
  const max = Math.max(1, ...series.map((d) => d.credits_micro));
  if (series.every((d) => d.credits_micro === 0)) return <EmptyState icon={Activity} title="区间内暂无消耗" />;
  return (
    <div className="flex h-40 items-end gap-1">
      {series.map((d) => {
        const h = (d.credits_micro / max) * 100;
        return (
          <div key={d.day} className="group relative flex flex-1 flex-col items-center justify-end" title={`${mmdd(d.day)} · ${credits(d.credits_micro)} 积分 · ${int(d.task_count)} 次`}>
            <div className="w-full rounded-t bg-brand/70 transition-colors group-hover:bg-brand" style={{ height: `${Math.max(d.credits_micro > 0 ? 4 : 0, h)}%` }} />
          </div>
        );
      })}
    </div>
  );
}
