import { useState, useMemo } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useNavigate } from 'react-router-dom';
import {
  createColumnHelper,
  flexRender,
  getCoreRowModel,
  getSortedRowModel,
  useReactTable,
  type SortingState,
} from '@tanstack/react-table';
import { ArrowUp, ArrowDown, RotateCcw } from 'lucide-react';
import { leaderboardApi, type LeaderboardEntry } from '../api/client';
import { Loading, ErrorState } from '../components/common/Loading';

const SQS_MAX = 80;

function SqsCell({ v }: { v: number | null }) {
  if (v == null) return <span style={{ color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 15 }}>—</span>;
  const pct = Math.min(100, (v / SQS_MAX) * 100);
  const color = v >= 70 ? 'var(--green)' : v >= 55 ? 'var(--cyan)' : v >= 40 ? 'var(--gold)' : 'var(--text3)';
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 110 }}>
      <span style={{ fontFamily: 'var(--font-mono)', fontSize: 15, fontWeight: 600, color, width: 40, textAlign: 'right', flexShrink: 0 }}>
        {v.toFixed(1)}
      </span>
      <div style={{ flex: 1, height: 4, background: 'var(--border-md)', borderRadius: 2 }}>
        <div style={{ width: `${pct}%`, height: '100%', background: color, borderRadius: 2 }} />
      </div>
    </div>
  );
}

function ReturnCell({ v, warn }: { v: number | null; warn?: boolean }) {
  if (v == null) return <span style={{ color: 'var(--text3)', fontFamily: 'var(--font-mono)', fontSize: 15 }}>—</span>;
  const color = warn ? 'var(--text2)' : v >= 0 ? 'var(--green)' : 'var(--red)';
  return (
    <span style={{ fontFamily: 'var(--font-mono)', fontSize: 15, color }}>
      {v >= 0 ? '+' : ''}{v.toFixed(1)}%
    </span>
  );
}

function MonoCell({ v, decimals = 1, suffix = '' }: { v: number | null; decimals?: number; suffix?: string }) {
  return (
    <span style={{ fontFamily: 'var(--font-mono)', fontSize: 15, color: v == null ? 'var(--text3)' : 'var(--text2)' }}>
      {v == null ? '—' : `${v.toFixed(decimals)}${suffix}`}
    </span>
  );
}

const col = createColumnHelper<LeaderboardEntry>();

const SORT_OPTIONS = [
  { value: 'sqs', label: 'SQS' },
  { value: 'rqs', label: 'RQS' },
  { value: 'wfqs', label: 'WFQS' },
  { value: 'deployment', label: 'Deploy' },
  { value: 'promotion', label: 'Promo' },
  { value: 'return', label: 'Return' },
];

export function LeaderboardPage() {
  const navigate = useNavigate();
  const [sortBy, setSortBy] = useState('sqs');
  const [includeRetired, setIncludeRetired] = useState(false);
  const [sorting, setSorting] = useState<SortingState>([]);
  const [top] = useState(200);

  const { data, isLoading, error, refetch, isFetching } = useQuery({
    queryKey: ['leaderboard', sortBy, includeRetired, top],
    queryFn: () => leaderboardApi.list({ sort_by: sortBy, include_retired: includeRetired, top }),
  });

  const columns = useMemo(() => [
    col.accessor('rank', {
      header: '#',
      size: 44,
      cell: i => (
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text3)' }}>
          {i.getValue()}
        </span>
      ),
    }),
    col.accessor('config_id', {
      header: 'ID',
      size: 60,
      cell: i => (
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 13, color: 'var(--text3)' }}>
          {i.getValue() ?? '—'}
        </span>
      ),
    }),
    col.accessor('experiment_name', {
      header: 'Strategy',
      size: 300,
      cell: i => (
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 14, color: 'var(--text1)', display: 'block', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: 290 }} title={i.getValue()}>
          {i.getValue()}
        </span>
      ),
    }),
    col.accessor('sqs_score', {
      header: 'SQS',
      size: 130,
      cell: i => <SqsCell v={i.getValue()} />,
    }),
    col.accessor('reset_common_window_score', {
      header: 'RCW',
      size: 72,
      cell: i => <MonoCell v={i.getValue()} />,
    }),
    col.accessor('train_total_return_pct', {
      header: 'Train',
      size: 72,
      cell: i => <ReturnCell v={i.getValue()} warn />,
    }),
    col.accessor('valid_total_return_pct', {
      header: 'Valid',
      size: 72,
      cell: i => <ReturnCell v={i.getValue()} warn />,
    }),
    col.accessor('total_return_pct', {
      header: 'Test',
      size: 72,
      cell: i => <ReturnCell v={i.getValue()} />,
    }),
    col.accessor('annualized_return_pct', {
      header: 'Ann%',
      size: 72,
      cell: i => <ReturnCell v={i.getValue()} />,
    }),
    col.accessor('max_drawdown_pct', {
      header: 'MaxDD',
      size: 72,
      cell: i => {
        const v = i.getValue();
        return <span style={{ fontFamily: 'var(--font-mono)', fontSize: 15, color: v == null ? 'var(--text3)' : 'var(--red)' }}>
          {v == null ? '—' : `${v.toFixed(1)}%`}
        </span>;
      },
    }),
    col.accessor('avg_gross_exposure_pct', {
      header: 'Exp%',
      size: 68,
      cell: i => <MonoCell v={i.getValue()} suffix="%" />,
    }),
    col.accessor('win_rate', {
      header: 'Win%',
      size: 68,
      cell: i => <MonoCell v={i.getValue()} suffix="%" />,
    }),
    col.accessor('profit_factor', {
      header: 'PF',
      size: 60,
      cell: i => <MonoCell v={i.getValue()} decimals={2} />,
    }),
    col.accessor('trade_count', {
      header: 'N',
      size: 56,
      cell: i => (
        <span style={{ fontFamily: 'var(--font-mono)', fontSize: 15, color: 'var(--text3)' }}>
          {i.getValue()}
        </span>
      ),
    }),
  ], []);

  const table = useReactTable({
    data: data?.entries ?? [],
    columns,
    state: { sorting },
    onSortingChange: setSorting,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
  });

  return (
    <div style={{ padding: '36px 40px' }} className="fade-up">
      {/* Header */}
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 28 }}>
        <div>
          <div style={{ fontFamily: 'var(--font-mono)', fontSize: 12, letterSpacing: '0.10em', color: 'var(--text3)', textTransform: 'uppercase', marginBottom: 6 }}>
            PUBLIC SQS v4 · {data?.total ?? '—'} entries
          </div>
          <h1 style={{ fontSize: 28, fontWeight: 700, color: 'var(--text1)', letterSpacing: '-0.02em' }}>Leaderboard</h1>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          {/* Sort selector */}
          <div style={{ display: 'flex', background: 'var(--bg1)', border: '1px solid var(--border-md)', borderRadius: 9, overflow: 'hidden' }}>
            {SORT_OPTIONS.map(o => (
              <button
                key={o.value}
                onClick={() => setSortBy(o.value)}
                style={{
                  padding: '8px 14px',
                  fontSize: 13,
                  fontFamily: 'var(--font-mono)',
                  border: 'none',
                  cursor: 'pointer',
                  transition: 'all 0.1s',
                  background: sortBy === o.value ? 'var(--cyan-dim)' : 'transparent',
                  color: sortBy === o.value ? 'var(--cyan)' : 'var(--text3)',
                  borderRight: '1px solid var(--border)',
                }}
              >
                {o.label}
              </button>
            ))}
          </div>
          <label style={{ display: 'flex', alignItems: 'center', gap: 7, fontSize: 14, color: 'var(--text3)', cursor: 'pointer', fontFamily: 'var(--font-mono)' }}>
            <input
              type="checkbox"
              checked={includeRetired}
              onChange={e => setIncludeRetired(e.target.checked)}
              style={{ width: 15, height: 15 }}
            />
            retired
          </label>
          <button
            onClick={() => refetch()}
            style={{
              width: 38, height: 38, display: 'flex', alignItems: 'center', justifyContent: 'center',
              background: 'var(--bg1)', border: '1px solid var(--border-md)', borderRadius: 8,
              color: 'var(--text3)', cursor: 'pointer', transition: 'all 0.12s',
            }}
            onMouseEnter={e => { (e.currentTarget as HTMLButtonElement).style.color = 'var(--cyan)'; }}
            onMouseLeave={e => { (e.currentTarget as HTMLButtonElement).style.color = 'var(--text3)'; }}
          >
            <RotateCcw size={15} style={{ animation: isFetching ? 'spin 1s linear infinite' : 'none' }} />
          </button>
        </div>
      </div>

      <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>

      {isLoading && <Loading />}
      {error && <ErrorState error={error as Error} />}

      {data && (
        <div style={{ background: 'var(--bg1)', border: '1px solid var(--border)', borderRadius: 12, overflow: 'hidden', boxShadow: '0 1px 3px rgba(0,0,0,0.04)' }}>
          <div style={{ overflowX: 'auto' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse' }}>
              <thead>
                {table.getHeaderGroups().map(hg => (
                  <tr key={hg.id} style={{ borderBottom: '1px solid var(--border-md)', background: 'var(--bg2)' }}>
                    {hg.headers.map(header => (
                      <th
                        key={header.id}
                        onClick={header.column.getToggleSortingHandler()}
                        style={{
                          padding: '13px 16px',
                          textAlign: 'left',
                          fontFamily: 'var(--font-mono)',
                          fontSize: 12,
                          fontWeight: 500,
                          letterSpacing: '0.07em',
                          textTransform: 'uppercase',
                          color: header.column.getIsSorted() ? 'var(--cyan)' : 'var(--text3)',
                          cursor: header.column.getCanSort() ? 'pointer' : 'default',
                          whiteSpace: 'nowrap',
                          width: header.getSize(),
                          userSelect: 'none',
                        }}
                      >
                        <div style={{ display: 'flex', alignItems: 'center', gap: 5 }}>
                          {flexRender(header.column.columnDef.header, header.getContext())}
                          {header.column.getIsSorted() === 'asc' && <ArrowUp size={12} />}
                          {header.column.getIsSorted() === 'desc' && <ArrowDown size={12} />}
                        </div>
                      </th>
                    ))}
                  </tr>
                ))}
              </thead>
              <tbody>
                {table.getRowModel().rows.map((row, idx) => (
                  <tr
                    key={row.id}
                    onClick={() => navigate(`/experiments/${encodeURIComponent(row.original.experiment_name)}`)}
                    style={{
                      borderBottom: idx < table.getRowModel().rows.length - 1 ? '1px solid var(--border)' : 'none',
                      cursor: 'pointer',
                      transition: 'background 0.1s',
                      background: idx % 2 === 1 ? 'rgba(0,0,0,0.018)' : 'transparent',
                    }}
                    onMouseEnter={e => (e.currentTarget.style.background = 'var(--cyan-dim)')}
                    onMouseLeave={e => (e.currentTarget.style.background = idx % 2 === 1 ? 'rgba(0,0,0,0.018)' : 'transparent')}
                  >
                    {row.getVisibleCells().map(cell => (
                      <td key={cell.id} style={{ padding: '10px 16px' }}>
                        {flexRender(cell.column.columnDef.cell, cell.getContext())}
                      </td>
                    ))}
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}
    </div>
  );
}
