/*
Copyright (C) 2025 QuantumNous

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.

For commercial licensing, please contact support@quantumnous.com
*/

import React, { useMemo, useState, useRef, useEffect, useCallback } from 'react';
import { TrendingUp, RefreshCw, ChevronDown } from 'lucide-react';
import Sparkline from './Sparkline';
import { renderQuota, renderNumber } from '../../helpers';

const formatMD = (d) => {
  const m = d.getMonth() + 1;
  const day = d.getDate();
  return `${m}/${day}`;
};

const ACCENT_COLORS = ['#10b981', '#3b82f6', '#8b5cf6', '#f59e0b'];
const DOT_COLOR = '#3b82f6';

const RANGE_OPTIONS = [
  { key: 'today', label: '今天' },
  { key: 'yesterday', label: '昨天' },
  { key: '24h', label: '近 24 小时' },
  { key: '7d', label: '近 7 天' },
  { key: '14d', label: '近 14 天' },
  { key: '30d', label: '近 30 天' },
  { key: 'thisMonth', label: '本月' },
  { key: 'lastMonth', label: '上月' },
];

const BentoTrend = ({
  dailyStats = [],
  topModels = [],
  className = '',
  onRefresh,
  loading = false,
  rangeKey = '7d',
  onRangeChange,
}) => {
  const [rangeOpen, setRangeOpen] = useState(false);
  const [customStart, setCustomStart] = useState('');
  const [customEnd, setCustomEnd] = useState('');
  const [tooltip, setTooltip] = useState(null); // { dayIdx, x, y } or null
  const rangeRef = useRef(null);
  const chartRef = useRef(null);

  useEffect(() => {
    const handler = (e) => {
      if (rangeRef.current && !rangeRef.current.contains(e.target)) {
        setRangeOpen(false);
      }
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, []);

  const selectedLabel = RANGE_OPTIONS.find((r) => r.key === rangeKey)?.label || '近 7 天';

  const handleApply = () => {
    if (customStart && customEnd) {
      onRangeChange('custom');
    }
    setRangeOpen(false);
  };

  const handleHover = useCallback((idx, cx, cy) => {
    if (idx < 0 || idx >= dailyStats.length) {
      setTooltip(null);
      return;
    }
    const rect = chartRef.current?.getBoundingClientRect();
    setTooltip({
      dayIdx: idx,
      x: rect ? cx - rect.left : cx,
      y: rect ? cy - rect.top - 120 : cy - 120,
    });
  }, [dailyStats.length]);

  const counts = useMemo(() => dailyStats.map((d) => d.count), [dailyStats]);
  const costs = useMemo(() => dailyStats.map((d) => d.cost), [dailyStats]);

  const totalCalls = counts.reduce((s, v) => s + v, 0);
  const totalCost = costs.reduce((s, v) => s + v, 0);
  const avg = totalCalls > 0 ? (totalCalls / Math.max(counts.length, 1)).toFixed(1) : '0.0';
  const peak = counts.length > 0 ? Math.max(...counts) : 0;
  const topMax = topModels[0]?.count || 0;

  const hoverDay = tooltip ? dailyStats[tooltip.dayIdx] : null;
  const hoverModels = hoverDay ? Object.entries(hoverDay.models || {}).sort((a, b) => b[1] - a[1]) : [];

  return (
    <div
      className={`relative flex flex-col gap-4 rounded-2xl border border-slate-200 bg-white p-6 transition-shadow hover:shadow-md dark:border-white/5 dark:bg-white/[0.02] dark:hover:shadow-black/20 ${className}`}
    >
      {/* Header */}
      <div className='flex items-center justify-between gap-3'>
        <div className='flex items-center gap-3'>
          <div className='flex h-10 w-10 items-center justify-center rounded-xl bg-blue-50 text-blue-600 dark:bg-blue-500/10 dark:text-blue-400'>
            <TrendingUp size={18} />
          </div>
          <div>
            <div className='text-sm font-semibold text-slate-900 dark:text-white'>Token 使用趋势</div>
            <div className='mt-0.5 text-[11px] text-slate-400 tabular-nums dark:text-white/40'>
              {selectedLabel}
              <span className='font-semibold text-slate-900 dark:text-white'> {totalCalls}</span> 次
              · 日均{' '}
              <span className='font-semibold text-slate-900 dark:text-white'>{avg}</span>
            </div>
          </div>
        </div>
        <div className='hidden text-right md:block'>
          <div className='text-[10px] uppercase tracking-wider text-slate-400 font-mono dark:text-white/30'>
            花费
          </div>
          <div className='font-mono text-sm font-semibold tabular-nums text-emerald-600 dark:text-emerald-400'>
            {totalCost > 0 ? renderQuota(totalCost) : '—'}
          </div>
        </div>
      </div>

      {/* Controls */}
      <div className='flex items-center justify-between'>
        <div className='flex items-center gap-2' ref={rangeRef}>
          <div className='relative'>
            <button
              onClick={() => setRangeOpen(!rangeOpen)}
              className='inline-flex items-center gap-1.5 rounded-full border border-slate-200 bg-white px-3 py-1.5 text-xs font-medium text-slate-700 transition-colors hover:border-slate-300 dark:border-white/10 dark:bg-white/[0.02] dark:text-white/70 dark:hover:bg-white/5'
            >
              {selectedLabel}
              <ChevronDown size={12} className='text-slate-400 dark:text-white/40' />
            </button>

            {rangeOpen && (
              <div className='absolute left-0 top-full z-50 mt-1 w-64 rounded-xl border border-slate-200 bg-white p-3 shadow-lg dark:border-white/10 dark:bg-neutral-900'>
                <div className='space-y-0.5'>
                  {RANGE_OPTIONS.map((opt) => (
                    <button
                      key={opt.key}
                      onClick={() => {
                        onRangeChange(opt.key);
                        setCustomStart('');
                        setCustomEnd('');
                        setRangeOpen(false);
                      }}
                      className={`w-full rounded-lg px-3 py-1.5 text-left text-xs transition-colors ${
                        rangeKey === opt.key
                          ? 'bg-blue-50 font-medium text-blue-700 dark:bg-blue-500/10 dark:text-blue-400'
                          : 'text-slate-600 hover:bg-slate-50 dark:text-white/60 dark:hover:bg-white/5'
                      }`}
                    >
                      {opt.label}
                    </button>
                  ))}
                </div>

                <div className='my-2 border-t border-slate-100 dark:border-white/5' />

                <div className='space-y-2'>
                  <div className='flex items-center gap-2'>
                    <input
                      type='date'
                      value={customStart}
                      onChange={(e) => setCustomStart(e.target.value)}
                      className='flex-1 rounded-lg border border-slate-200 bg-white px-2 py-1 text-xs text-slate-700 outline-none focus:border-blue-400 dark:border-white/10 dark:bg-white/[0.02] dark:text-white/70'
                      placeholder='开始日期'
                    />
                    <span className='text-xs text-slate-400'>—</span>
                    <input
                      type='date'
                      value={customEnd}
                      onChange={(e) => setCustomEnd(e.target.value)}
                      className='flex-1 rounded-lg border border-slate-200 bg-white px-2 py-1 text-xs text-slate-700 outline-none focus:border-blue-400 dark:border-white/10 dark:bg-white/[0.02] dark:text-white/70'
                      placeholder='结束日期'
                    />
                  </div>
                  <button
                    onClick={handleApply}
                    disabled={!customStart || !customEnd}
                    className='w-full rounded-lg bg-blue-600 py-1.5 text-xs font-medium text-white transition-colors hover:bg-blue-700 disabled:opacity-40 dark:bg-blue-500 dark:hover:bg-blue-600'
                  >
                    应用
                  </button>
                </div>
              </div>
            )}
          </div>

          <button
            onClick={onRefresh}
            disabled={loading}
            className='flex h-7 w-7 items-center justify-center rounded-full border border-slate-200 bg-white text-slate-500 transition-colors hover:border-slate-300 hover:bg-slate-50 hover:text-slate-700 disabled:opacity-50 dark:border-white/10 dark:bg-white/[0.02] dark:text-white/60 dark:hover:bg-white/5 dark:hover:text-white'
            title='刷新'
          >
            <RefreshCw size={12} className={loading ? 'animate-spin' : ''} />
          </button>
        </div>

        {/* Peak / total indicators */}
        <div className='hidden items-center gap-3 sm:flex'>
          <div className='flex items-center gap-1.5 text-[11px] text-slate-400 dark:text-white/40'>
            <span className='inline-block h-1.5 w-1.5 rounded-full bg-blue-500' />
            峰值 <span className='font-semibold text-slate-700 dark:text-white/80'>{peak}</span> 次
          </div>
          <div className='flex items-center gap-1.5 text-[11px] text-slate-400 dark:text-white/40'>
            合计 <span className='font-semibold text-slate-700 dark:text-white/80'>{totalCalls}</span> 次
          </div>
        </div>
      </div>

      {/* Chart area */}
      <div ref={chartRef} className='relative flex min-h-[80px] flex-1 items-end text-blue-500'>
        <Sparkline data={counts} height={80} stroke={DOT_COLOR} onHover={handleHover} />

        {/* Tooltip */}
        {tooltip && hoverDay && (
          <div
            className='pointer-events-none absolute z-50 min-w-[180px] rounded-xl border border-slate-200 bg-white px-4 py-3 shadow-lg dark:border-white/10 dark:bg-neutral-900'
            style={{ left: tooltip.x, top: tooltip.y, transform: 'translate(-50%, -100%)' }}
          >
            <div className='mb-1 text-xs font-semibold text-slate-900 dark:text-white'>
              {hoverDay.date.getMonth() + 1}月{hoverDay.date.getDate()}日
            </div>
            <div className='mb-2 flex items-center gap-3 text-[11px] text-slate-500 dark:text-white/50'>
              <span>调用 <b className='text-slate-900 dark:text-white'>{hoverDay.count}</b> 次</span>
              <span>花费 <b className='text-slate-900 dark:text-white'>{renderQuota(hoverDay.cost)}</b></span>
            </div>
            {hoverModels.length > 0 && (
              <>
                <div className='mb-1.5 h-px bg-slate-100 dark:bg-white/5' />
                <div className='space-y-1'>
                  {hoverModels.slice(0, 5).map(([name, count], i) => (
                    <div key={name} className='flex items-center gap-2 text-[11px]'>
                      <span
                        className='inline-block h-1.5 w-1.5 rounded-full shrink-0'
                        style={{ backgroundColor: ACCENT_COLORS[i % ACCENT_COLORS.length] }}
                      />
                      <span className='min-w-0 flex-1 truncate text-slate-600 dark:text-white/70'>
                        {name}
                      </span>
                      <span className='shrink-0 font-mono tabular-nums text-slate-400 dark:text-white/40'>
                        {count}
                      </span>
                    </div>
                  ))}
                </div>
              </>
            )}
          </div>
        )}
      </div>

      {/* Date labels */}
      <div className='flex items-center justify-between text-[11px]'>
        <div className='flex w-full items-center justify-between tabular-nums'>
          {dailyStats.map((d, i) => {
            const isHovered = tooltip?.dayIdx === i;
            return (
              <span
                key={i}
                className={`text-center text-xs transition-colors ${
                  isHovered
                    ? 'font-semibold text-blue-600 dark:text-blue-400'
                    : 'text-slate-500 dark:text-white/50'
                }`}
              >
                {formatMD(d.date)}
              </span>
            );
          })}
        </div>
      </div>

      {/* Top 5 Models */}
      {topModels.length > 0 && (
        <div className='border-t border-slate-100 pt-4 dark:border-white/5'>
          <div className='mb-2 flex items-center justify-between text-[11px] uppercase tracking-wider text-slate-400 dark:text-white/40'>
            <span>Top 5 模型</span>
            <span className='font-mono normal-case tracking-normal'>近 30 日</span>
          </div>
          <ul className='space-y-1.5'>
            {topModels.map((m, i) => {
              const pct = topMax > 0 ? (m.count / topMax) * 100 : 0;
              const color = ACCENT_COLORS[i % ACCENT_COLORS.length];
              return (
                <li
                  key={m.name + i}
                  className='flex items-center gap-3 text-xs'
                  title={m.name}
                >
                  <span className='w-3 shrink-0 text-right font-mono text-[10px] tabular-nums' style={{ color }}>
                    {i + 1}
                  </span>
                  <span className='min-w-0 flex-1 truncate text-slate-700 dark:text-white/80'>
                    {m.name}
                  </span>
                  <div className='hidden h-1 w-24 overflow-hidden rounded-full bg-slate-100 sm:block dark:bg-white/5'>
                    <div
                      className='h-full rounded-full'
                      style={{ width: `${pct}%`, backgroundColor: color }}
                    />
                  </div>
                  <span className='w-12 shrink-0 text-right font-mono tabular-nums text-slate-500 dark:text-white/60'>
                    {m.count}
                  </span>
                </li>
              );
            })}
          </ul>
        </div>
      )}
    </div>
  );
};

export default BentoTrend;
