import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { createRoot } from "react-dom/client";
import {
  BarChart3,
  CalendarDays,
  ChevronDown,
  Check,
  Info,
  Layers3,
  RefreshCcw,
  Sparkles,
  TrendingUp
} from "lucide-react";
import { sampleSummary } from "./sampleData";
import { formatTokensZh } from "./displayFormat";
import "./styles.css";

const providers = ["Claude", "Codex", "Gemini"];
const providerColors = {
  Claude: "#2e83ff",
  Codex: "#9b5cf6",
  Gemini: "#2dd4cf"
};

function App() {
  const [summary, setSummary] = useState(sampleSummary);
  const [status, setStatus] = useState("loading");
  const [lastUpdated, setLastUpdated] = useState("");
  const [refreshCount, setRefreshCount] = useState(0);
  const [range, setRange] = useState("近 30 天");
  const [trendMode, setTrendMode] = useState("每日");
  const [shareMode, setShareMode] = useState("按 Tokens");
  const [toolFilter, setToolFilter] = useState("全部工具");
  const scanningRef = useRef(false);

  const refresh = useCallback(async ({ silent = false } = {}) => {
    if (scanningRef.current) return;
    scanningRef.current = true;
    if (!silent) setStatus("loading");
    try {
      if (window.tokenLens?.scanUsage) {
        const data = await window.tokenLens.scanUsage();
        setSummary(data);
        setStatus("ready");
        setLastUpdated(new Date(data.generatedAt).toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit" }));
        setRefreshCount((count) => count + 1);
      } else {
        setSummary(sampleSummary);
        setStatus("preview");
        setLastUpdated("预览数据");
      }
    } catch (error) {
      setStatus("error");
      setLastUpdated("扫描失败");
      console.error(error);
    } finally {
      scanningRef.current = false;
    }
  }, []);

  useEffect(() => {
    refresh();
    const timer = window.setInterval(() => {
      refresh({ silent: true });
    }, 15_000);
    return () => window.clearInterval(timer);
  }, [refresh]);

  const totalByProvider = useMemo(() => providers.reduce((sum, provider) => {
    return sum + (summary.providerTotals?.[provider]?.totalTokens || 0);
  }, 0), [summary]);

  const sourceRows = summary.sourceRows?.length ? summary.sourceRows : sampleSummary.sourceRows;
  const filteredRows = toolFilter === "全部工具" ? sourceRows : sourceRows.filter((row) => row.provider === toolFilter);
  const insights = summary.insights?.length ? summary.insights.slice(0, 3) : sampleSummary.insights;

  return (
    <div className="app-shell">
      <main className="main-pane">
        <TopBar
          onRefresh={() => refresh()}
          status={status}
          lastUpdated={lastUpdated}
          refreshCount={refreshCount}
          range={range}
          setRange={setRange}
        />
        <section className="dashboard">
          <MetricCards summary={summary} />

          <section className="middle-grid">
            <Panel
              title="Tokens 使用趋势"
              control={<Dropdown value={trendMode} options={["每日", "每周"]} onChange={setTrendMode} />}
            >
              <TrendChart data={summary.dailyTrend || []} />
            </Panel>

            <Panel
              title="使用占比"
              control={<Dropdown value={shareMode} options={["按 Tokens", "按占比"]} onChange={setShareMode} />}
            >
              <UsageShare providerTotals={summary.providerTotals || {}} total={totalByProvider} />
            </Panel>
          </section>

          <section className="bottom-grid">
            <ProviderBreakdown rows={filteredRows} toolFilter={toolFilter} setToolFilter={setToolFilter} />
            <Insights insights={insights} />
          </section>
        </section>
      </main>
    </div>
  );
}

function TopBar({ onRefresh, status, lastUpdated, refreshCount, range, setRange }) {
  return (
    <header className="topbar">
      <div className="brand">
        <BarChart3 size={23} />
        <span>TokenLens 用量统计</span>
        <span className={`live-pill ${status}`}>
          <i />
          {status === "error" ? "扫描异常" : "每 15 秒自动刷新"}
        </span>
      </div>
      <div className="toolbar">
        <Dropdown
          value={range}
          options={["近 7 天", "近 30 天", "本月", "全部"]}
          onChange={setRange}
          icon={<CalendarDays size={18} />}
          className="toolbar-dropdown"
        />
        <button className="toolbar-button primary" onClick={onRefresh}>
          <RefreshCcw size={18} className={status === "loading" ? "spin" : ""} />
          同步
        </button>
        <div className="refresh-meta">
          <span>{lastUpdated ? `上次更新 ${lastUpdated}` : "准备扫描"}</span>
          <small>已刷新 {refreshCount} 次</small>
        </div>
      </div>
    </header>
  );
}

function MetricCards({ summary }) {
  const cards = [
    {
      label: "今日 Tokens",
      value: formatTokensZh(summary.cards?.todayTokens || 0),
      detail: "本地今日已统计",
      trend: "实时",
      tone: "blue",
      icon: Layers3
    },
    {
      label: "本月 Tokens",
      value: formatTokensZh(summary.cards?.monthTokens || 0),
      detail: "按本地时区汇总",
      trend: "月度",
      tone: "green",
      icon: Sparkles
    },
    {
      label: "历史总量",
      value: formatTokensZh(summary.cards?.totalTokens || 0),
      detail: `已扫描 ${summary.cards?.sessionCount || 0} 个会话`,
      trend: "全部",
      tone: "violet",
      icon: Check
    },
    {
      label: "缓存命中",
      value: `${summary.cards?.cacheHitRate || 0}%`,
      detail: "来自缓存上下文",
      trend: "缓存",
      tone: "orange",
      icon: TrendingUp
    }
  ];

  return (
    <section className="metric-grid">
      {cards.map((card, index) => {
        const Icon = card.icon;
        return (
          <article className="metric-card" key={card.label} style={{ "--i": index }}>
            <div className={`metric-icon ${card.tone}`}>
              <Icon size={25} />
            </div>
            <div className="metric-copy">
              <div className="metric-label">{card.label}<Info size={14} /></div>
              <div className="metric-value">{card.value}</div>
              <div className="metric-detail">
                <strong className={card.tone}>{card.trend}</strong>
                <span>{card.detail}</span>
              </div>
            </div>
          </article>
        );
      })}
    </section>
  );
}

function Panel({ title, control, children }) {
  return (
    <article className="panel">
      <div className="panel-header">
        <h2>{title}</h2>
        {control}
      </div>
      {children}
    </article>
  );
}

function Dropdown({ value, options, onChange, icon, className = "" }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    function close(event) {
      if (!ref.current?.contains(event.target)) setOpen(false);
    }
    document.addEventListener("pointerdown", close);
    return () => document.removeEventListener("pointerdown", close);
  }, []);

  return (
    <div className={`dropdown ${className}`} ref={ref}>
      <button className="dropdown-trigger" onClick={() => setOpen((current) => !current)}>
        {icon}
        {value}
        <ChevronDown size={16} className={open ? "chevron open" : "chevron"} />
      </button>
      {open ? (
        <div className="dropdown-menu">
          {options.map((option) => (
            <button
              className={option === value ? "selected" : ""}
              key={option}
              onClick={() => {
                onChange(option);
                setOpen(false);
              }}
            >
              {option}
            </button>
          ))}
        </div>
      ) : null}
    </div>
  );
}

function TrendChart({ data }) {
  const chartData = data.length ? data.slice(-24) : sampleSummary.dailyTrend;
  const width = 640;
  const height = 235;
  const left = 58;
  const right = 18;
  const top = 18;
  const bottom = 34;
  const maxValue = Math.max(1, ...chartData.flatMap((item) => providers.map((provider) => item[provider] || 0)));
  const plotWidth = width - left - right;
  const plotHeight = height - top - bottom;

  const x = (index) => left + (index / Math.max(chartData.length - 1, 1)) * plotWidth;
  const y = (value) => top + plotHeight - (value / maxValue) * plotHeight;
  const lines = providers.map((provider) => ({
    provider,
    points: chartData.map((item, index) => `${x(index)},${y(item[provider] || 0)}`).join(" ")
  }));

  const labelIndexes = [0, 6, 12, 18, chartData.length - 1].filter((index, pos, arr) => index >= 0 && arr.indexOf(index) === pos);

  return (
    <>
      <svg className="trend-chart" viewBox={`0 0 ${width} ${height}`} role="img" aria-label="Tokens 使用趋势">
        {[0, 0.25, 0.5, 0.75, 1].map((step) => {
          const lineY = top + plotHeight * step;
          const value = maxValue * (1 - step);
          return (
            <g key={step}>
              <line className="grid-line" x1={left} y1={lineY} x2={width - right} y2={lineY} />
              <text className="axis-label" x="12" y={lineY + 4}>{formatTokensZh(value)}</text>
            </g>
          );
        })}
        {labelIndexes.map((index) => (
          <text className="axis-label" key={index} x={x(index) - 20} y={height - 8}>
            {shortDate(chartData[index]?.date)}
          </text>
        ))}
        {lines.map((line) => (
          <polyline
            key={line.provider}
            className="trend-line"
            points={line.points}
            style={{ stroke: providerColors[line.provider] }}
          />
        ))}
        {lines.map((line) => chartData.filter((_, index) => index % 5 === 0 || index === chartData.length - 1).map((item, dotIndex) => (
          <circle
            key={`${line.provider}-${dotIndex}`}
            cx={x(chartData.indexOf(item))}
            cy={y(item[line.provider] || 0)}
            r="4"
            fill={providerColors[line.provider]}
          />
        )))}
      </svg>
      <Legend />
    </>
  );
}

function UsageShare({ providerTotals, total }) {
  const safeTotal = total || 1;
  let cursor = 0;
  const gradient = providers.map((provider) => {
    const share = ((providerTotals[provider]?.totalTokens || 0) / safeTotal) * 360;
    const start = cursor;
    cursor += share;
    return `${providerColors[provider]} ${start}deg ${cursor}deg`;
  }).join(", ");

  return (
    <div className="share-body">
      <div className="donut" style={{ background: `conic-gradient(${gradient})` }}>
        <div className="donut-center">
          <strong>{formatTokensZh(total)}</strong>
          <span>本月</span>
        </div>
      </div>
      <div className="share-list">
        {providers.map((provider) => {
          const providerTotal = providerTotals[provider]?.totalTokens || 0;
          const percent = total ? Math.round((providerTotal / total) * 100) : 0;
          return (
            <div className="share-row" key={provider}>
              <div>
                <span className="legend-name"><i style={{ background: providerColors[provider] }} />{provider}</span>
                <small>{formatTokensZh(providerTotal)} Tokens</small>
              </div>
              <strong>{percent}%</strong>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function ProviderBreakdown({ rows, toolFilter, setToolFilter }) {
  return (
    <article className="panel table-panel">
      <div className="panel-header table-title">
        <h2>工具明细</h2>
        <Dropdown value={toolFilter} options={["全部工具", "Claude", "Codex", "Gemini"]} onChange={setToolFilter} />
      </div>
      <table>
        <thead>
          <tr>
            <th>工具</th>
            <th>输入</th>
            <th>输出</th>
            <th>缓存</th>
            <th>总量</th>
            <th>趋势</th>
            <th />
          </tr>
        </thead>
        <tbody>
          {rows.map((row, index) => (
            <tr key={`${row.provider}-${row.source}-${index}`}>
              <td><ProviderName provider={row.provider} /></td>
              <td>{formatTokensZh(row.inputTokens)}</td>
              <td>{formatTokensZh(row.outputTokens)}</td>
              <td>{formatTokensZh(row.cachedTokens)}</td>
              <td>{formatTokensZh(row.totalTokens)}</td>
              <td><Sparkline provider={row.provider} seed={index} /></td>
              <td className="more">⋮</td>
            </tr>
          ))}
        </tbody>
      </table>
      <div className="table-footer">
        <span>显示 {rows.length} 个本地工具 · 不上传对话内容</span>
        <button>查看原始报告 →</button>
      </div>
    </article>
  );
}

function ProviderName({ provider }) {
  return (
    <div className="provider-name">
      <span className={`provider-logo ${provider.toLowerCase()}`}>{provider === "Gemini" ? "" : provider[0]}</span>
      {provider}
    </div>
  );
}

function Sparkline({ provider, seed }) {
  const base = [
    [17, 12, 16, 8, 12, 6, 10, 4, 8, 5, 9],
    [18, 11, 15, 17, 10, 13, 7, 12, 6, 8, 4],
    [16, 16, 10, 18, 14, 9, 12, 6, 5, 8, 8]
  ][seed % 3];
  const points = base.map((value, index) => `${index * 7},${value}`).join(" ");
  return (
    <svg className="sparkline" viewBox="0 0 74 22">
      <polyline points={points} style={{ stroke: providerColors[provider] || "#4b99ff" }} />
    </svg>
  );
}

function Insights({ insights }) {
  return (
    <article className="panel insight-panel">
      <div className="panel-header table-title">
        <h2>洞察提醒</h2>
        <button>查看全部</button>
      </div>
      <div className="insight-list">
        {insights.map((insight, index) => (
          <div className={`insight ${insight.tone}`} key={`${insight.title}-${index}`}>
            <div className="insight-icon">{insight.tone === "good" ? "✓" : insight.tone === "warn" ? "!" : "↗"}</div>
            <div className="insight-time">{index + 1} 小时</div>
            <strong>{insight.title}</strong>
            <span>{insight.copy}</span>
          </div>
        ))}
      </div>
    </article>
  );
}

function Legend() {
  return (
    <div className="legend">
      {providers.map((provider) => (
        <span key={provider}><i style={{ background: providerColors[provider] }} />{provider}</span>
      ))}
    </div>
  );
}

function shortDate(value) {
  if (!value) return "";
  const [, month, day] = value.split("-");
  return `${month}/${day}`;
}

createRoot(document.getElementById("root")).render(<App />);
