import { Fragment, useState } from 'react'
import { useChainTokenRows, useAllWalletTokenRows } from '../model/useChainTokenRows'
import type { Token } from '../model/tokens'
import { SendModal, TICKER_TO_CHAIN, type Chain } from '@widgets/send-modal'
import { ReceiveModal } from '@widgets/receive-modal'
import { COIN_ICONS } from '@shared/assets/coins'
import styles from './TokenTable.module.css'

const CHAIN_META: Record<Chain, { label: string; icon: string }> = {
  BTC: { label: 'Bitcoin', icon: COIN_ICONS.BTC },
  ETH: { label: 'Ethereum', icon: COIN_ICONS.ETH },
  SOL: { label: 'Solana', icon: COIN_ICONS.SOL },
  TRX: { label: 'Tron', icon: COIN_ICONS.TRX },
  BSC: { label: 'BNB Chain', icon: COIN_ICONS.BNB },
}

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

interface ChainGroup {
  chain: Chain
  rows: Token[]
  totalUsd: number
}

/** Group rows by chain, preserving first-seen order (= CHAINS order from the hook). */
function groupByChainOrder(rows: Token[]): ChainGroup[] {
  const groups: ChainGroup[] = []
  const index = new Map<Chain, ChainGroup>()
  for (const row of rows) {
    const chain = (row.chain ?? 'ETH') as Chain
    let group = index.get(chain)
    if (!group) {
      group = { chain, rows: [], totalUsd: 0 }
      index.set(chain, group)
      groups.push(group)
    }
    group.rows.push(row)
    group.totalUsd += row.usdValue ?? 0
  }
  return groups
}

function rowKey(t: Token): string {
  return t.id ?? t.ticker
}

interface ViewProps {
  rows: Token[]
  isLoading: boolean
  /** Network used when a row does not carry its own chain. */
  fallbackChain?: Chain
  /** Group rows under per-network headers (used by the "all coins" view). */
  groupByChain?: boolean
}

function TokenTableView({ rows, isLoading, fallbackChain = 'ETH', groupByChain = false }: ViewProps) {
  const [favs, setFavs] = useState<Record<string, boolean>>({})
  const [sendModal, setSendModal] = useState<{ open: boolean; network: Chain }>({
    open: false,
    network: 'ETH',
  })
  const [receiveModal, setReceiveModal] = useState<{ open: boolean; chain: Chain }>({
    open: false,
    chain: 'ETH',
  })

  function resolveChain(row: Token): Chain {
    return row.chain ?? TICKER_TO_CHAIN[row.ticker] ?? fallbackChain
  }

  function openSend(row: Token) {
    setSendModal({ open: true, network: resolveChain(row) })
  }

  function closeSend() {
    setSendModal((s) => ({ ...s, open: false }))
  }

  function openReceive(row: Token) {
    setReceiveModal({ open: true, chain: resolveChain(row) })
  }

  function closeReceive() {
    setReceiveModal((s) => ({ ...s, open: false }))
  }

  function toggleFav(key: string) {
    setFavs((prev) => ({ ...prev, [key]: !prev[key] }))
  }

  const sendIcon = (
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#4A6DFF" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M7 17L17 7M17 7H7M17 7v10" />
    </svg>
  )

  const receiveIcon = (
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#00C48C" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M17 7L7 17M7 17H17M7 17V7" />
    </svg>
  )

  function renderRow(t: Token) {
    const key = rowKey(t)
    return (
      <tr key={key}>
        <td>
          <button
            className={`${styles.star} ${favs[key] ? styles.starOn : ''}`}
            onClick={() => toggleFav(key)}
            type="button"
            aria-label={favs[key] ? 'Убрать из избранного' : 'В избранное'}
          >
            ★
          </button>
        </td>
        <td>
          <div className={styles.tokId}>
            <div className={styles.tokLogo} style={{ background: t.color }}>
              {t.logo ? <img src={t.logo} alt={t.ticker} className={''} /> : t.ticker[0]}
            </div>
            <div className={styles.balCol}>
              <b className={styles.cardTicker}>{t.ticker}</b>
              <span className={styles.noFont}>{t.name}</span>
            </div>
          </div>
        </td>
        <td className={styles.right}>
          <span className={styles.price}>{t.price}</span>
        </td>
        <td className={styles.right}>
          <div className={styles.balCol}>
            <b>{t.bal}</b>
            <span>{t.usd}</span>
          </div>
        </td>
        <td className={styles.center}>
          <div className={styles.btnGroup}>
            <button
              className={styles.receiveBtn}
              type="button"
              onClick={(e) => { e.stopPropagation(); openReceive(t) }}
            >
              {receiveIcon}
              Получить
            </button>
            <button
              className={styles.sendBtn}
              type="button"
              onClick={(e) => { e.stopPropagation(); openSend(t) }}
            >
              {sendIcon}
              Отправить
            </button>
          </div>
        </td>
      </tr>
    )
  }

  function renderCard(t: Token) {
    const key = rowKey(t)
    return (
      <div key={key} className={styles.card}>
        <button
          className={`${styles.star} ${favs[key] ? styles.starOn : ''}`}
          onClick={() => toggleFav(key)}
          type="button"
          aria-label={favs[key] ? 'Убрать из избранного' : 'В избранное'}
        >
          ★
        </button>
        <div className={styles.tokLogo} style={{ background: t.color }}>
          {t.logo
            ? <img src={t.logo} alt={t.ticker} className={''} />
            : t.ticker[0]}
        </div>
        <div className={styles.cardInfo}>
          <div className={styles.cardTop}>
            <div>
              <span className={styles.cardTicker}>{t.ticker}</span>
              <span className={styles.cardName}>{t.name}</span>
            </div>
            <span className={styles.cardBalCrypto}>{t.bal}</span>
          </div>
          <div className={styles.cardBot}>
            <span className={styles.cardPrice}>{t.price}</span>
            <span className={styles.cardBalUsd}>{t.usd}</span>
          </div>
        </div>
      </div>
    )
  }

  function tableGroupHeader(group: ChainGroup) {
    const meta = CHAIN_META[group.chain]
    return (
      <tr key={`h-${group.chain}`} className={styles.groupHeader}>
        <td colSpan={5}>
          <div className={styles.groupHeaderInner}>
            <span className={styles.groupLabel}>
              <img src={meta.icon} alt="" className={styles.groupIcon} />
              {meta.label}
            </span>
            <span className={styles.groupTotal}>{formatUsd(group.totalUsd)}</span>
          </div>
        </td>
      </tr>
    )
  }

  function mobileGroupHeader(group: ChainGroup) {
    const meta = CHAIN_META[group.chain]
    return (
      <div key={`mh-${group.chain}`} className={styles.mobileGroupHeader}>
        <span className={styles.groupLabel}>
          <img src={meta.icon} alt="" className={styles.groupIcon} />
          {meta.label}
        </span>
        <span className={styles.groupTotal}>{formatUsd(group.totalUsd)}</span>
      </div>
    )
  }

  const groups = groupByChain ? groupByChainOrder(rows) : null

  return (
    <>
      <div className={`${styles.wrap} ${isLoading ? styles.loading : ''}`}>
        <table className={styles.table}>
          <thead>
            <tr>
              <th className={styles.thStar}>☆</th>
              <th>Токены</th>
              <th className={styles.right}>Цена</th>
              <th className={styles.right}>Баланс</th>
              <th className={styles.center}></th>
            </tr>
          </thead>
          <tbody>
            {groups
              ? groups.map((g) => (
                  <Fragment key={g.chain}>
                    {tableGroupHeader(g)}
                    {g.rows.map(renderRow)}
                  </Fragment>
                ))
              : rows.map(renderRow)}
          </tbody>
        </table>

        {/* Mobile card list */}
        <div className={styles.mobileList}>
          {groups
            ? groups.map((g) => (
                <Fragment key={g.chain}>
                  {mobileGroupHeader(g)}
                  {g.rows.map(renderCard)}
                </Fragment>
              ))
            : rows.map(renderCard)}
        </div>
      </div>

      <div className={styles.mobileActions}>
        <button className={styles.receiveBtn} type="button" onClick={() => rows[0] && openReceive(rows[0])}>
          {receiveIcon}
          Получить
        </button>
        <button className={styles.sendBtn} type="button" onClick={() => rows[0] && openSend(rows[0])}>
          {sendIcon}
          Отправить
        </button>
      </div>

      <SendModal
        open={sendModal.open}
        onClose={closeSend}
        network={sendModal.network}
        tokens={rows}
      />
      <ReceiveModal
        open={receiveModal.open}
        onClose={closeReceive}
        chain={receiveModal.chain}
      />
    </>
  )
}

interface Props {
  chain: Chain
}

export function TokenTable({ chain }: Props) {
  const { rows, isLoading } = useChainTokenRows(chain)
  return <TokenTableView rows={rows} isLoading={isLoading} fallbackChain={chain} />
}

export function AllTokenTable() {
  const { rows, isLoading } = useAllWalletTokenRows()
  return <TokenTableView rows={rows} isLoading={isLoading} groupByChain />
}
