import { useMemo, useState } from 'react'
import { Spinner } from '@shared/ui'
import type { Pool } from '@features/pools'
import { formatFeeTier } from '../model/meta'
import styles from './PoolsTable.module.css'

interface Props {
  pools: Pool[]
  selected: string | null
  onSelect: (poolAddress: string) => void
  loading?: boolean
  error?: string | null
}

const DASH = '—'

type SortKey = 'pair' | 'feeTier' | 'currentPrice' | 'tvlUSD' | 'volumeUSD24h' | 'aprPercent'
type SortDir = 'desc' | 'asc'

function formatUsd(value: number | null): string {
  if (value == null) return DASH
  if (value >= 1_000_000) return `$${(value / 1_000_000).toFixed(2)}M`
  if (value >= 1_000) return `$${(value / 1_000).toFixed(2)}K`
  return `$${value.toFixed(2)}`
}

function formatPrice(value: number): string {
  return value.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
}

// APR обрезаем до 3 знаков после запятой и убираем лишние нули.
function formatApr(value: number | null): string {
  if (value == null) return DASH
  return `${parseFloat(value.toFixed(3))}%`
}

function pairName(p: Pool): string {
  return `${p.symbol0}/${p.symbol1}`
}

// Числовые поля могут быть null — null уходит вниз независимо от направления.
function compare(a: Pool, b: Pool, key: SortKey, dir: SortDir): number {
  if (key === 'pair') {
    const cmp = pairName(a).localeCompare(pairName(b))
    return dir === 'asc' ? cmp : -cmp
  }
  const av = a[key]
  const bv = b[key]
  if (av == null && bv == null) return 0
  if (av == null) return 1
  if (bv == null) return -1
  const cmp = av - bv
  return dir === 'asc' ? cmp : -cmp
}

export function PoolsTable({ pools, selected, onSelect, loading, error }: Props) {
  const [sortKey, setSortKey] = useState<SortKey | null>(null)
  const [sortDir, setSortDir] = useState<SortDir | null>(null)

  function handleSort(key: SortKey) {
    if (sortKey !== key) {
      // Новая колонка — начинаем с убывания.
      setSortKey(key)
      setSortDir('desc')
      return
    }
    // Цикл по той же колонке: убывание → возрастание → по умолчанию.
    if (sortDir === 'desc') {
      setSortDir('asc')
    } else if (sortDir === 'asc') {
      setSortKey(null)
      setSortDir(null)
    } else {
      setSortDir('desc')
    }
  }

  const sortedPools = useMemo(() => {
    if (!sortKey || !sortDir) return pools
    return [...pools].sort((a, b) => compare(a, b, sortKey, sortDir))
  }, [pools, sortKey, sortDir])

  function sortArrow(key: SortKey): string {
    if (sortKey !== key || !sortDir) return ''
    return sortDir === 'desc' ? ' ▼' : ' ▲'
  }

  const columns: { key: SortKey; label: string; align: 'left' | 'right' }[] = [
    { key: 'pair', label: 'Пул', align: 'left' },
    { key: 'feeTier', label: 'Комиссия', align: 'right' },
    { key: 'currentPrice', label: 'Цена', align: 'right' },
    { key: 'tvlUSD', label: 'TVL', align: 'right' },
    { key: 'volumeUSD24h', label: 'Объём 24ч', align: 'right' },
    { key: 'aprPercent', label: 'APR', align: 'right' },
  ]

  return (
    <div className={styles.card}>
      <div className={styles.head}>
        <span className={styles.title}>Курируемые пулы</span>
      </div>

      {loading && <Spinner label="Загрузка пулов" />}
      {!loading && error && <div className={styles.message}>{error}</div>}
      {!loading && !error && pools.length === 0 && (
        <div className={styles.message}>Курируемых пулов пока нет.</div>
      )}

      {!loading && !error && pools.length > 0 && (
      <div className={styles.scroll}>
        <table className={styles.table}>
          <thead>
            <tr>
              {columns.map((col) => (
                <th
                  key={col.key}
                  className={`${styles.sortable} ${col.align === 'left' ? styles.thLeft : ''}`}
                  onClick={() => handleSort(col.key)}
                  aria-sort={sortKey === col.key ? (sortDir === 'asc' ? 'ascending' : 'descending') : 'none'}
                >
                  {col.label}
                  <span className={styles.arrow}>{sortArrow(col.key)}</span>
                </th>
              ))}
              <th aria-label="Действие" />
            </tr>
          </thead>
          <tbody>
            {sortedPools.map((p) => {
              const isSelected = p.poolAddress === selected
              return (
                <tr
                  key={p.poolAddress}
                  className={isSelected ? styles.rowSelected : styles.row}
                  onClick={() => onSelect(p.poolAddress)}
                >
                  <td className={styles.tdLeft}>
                    <span className={styles.pairName}>
                      {p.symbol0}/{p.symbol1}
                    </span>
                  </td>
                  <td>
                    <span className={styles.fee}>{formatFeeTier(p.feeTier)}</span>
                  </td>
                  <td className={styles.mono}>{formatPrice(p.currentPrice)}</td>
                  <td className={styles.mono}>{formatUsd(p.tvlUSD)}</td>
                  <td className={styles.mono}>{formatUsd(p.volumeUSD24h)}</td>
                  <td className={`${styles.mono} ${styles.apr}`}>{formatApr(p.aprPercent)}</td>
                  <td className={styles.tdAction}>
                    <button
                      type="button"
                      className={isSelected ? styles.btnSelected : styles.btn}
                      onClick={(e) => {
                        e.stopPropagation()
                        onSelect(p.poolAddress)
                      }}
                    >
                      {isSelected ? 'Выбран' : 'Выбрать'}
                    </button>
                  </td>
                </tr>
              )
            })}
          </tbody>
        </table>
      </div>
      )}
    </div>
  )
}
