import { useEffect, useMemo, useState } from 'react'
import { Notification } from '@shared/ui'
import { useDebounce } from '@shared/lib/hooks/useDebounce'
import {
  usePools,
  useLpPositions,
  useLpQuote,
  useAddLp,
  useRemoveLp,
  getPoolsErrorMessage,
  type LpDepositInput,
  type LpPosition,
} from '@features/pools'
import { displaySymbol } from '../model/meta'
import { PoolsTable } from './PoolsTable'
import { LpDepositCard } from './LpDepositCard'
import { LpPositionsPanel } from './LpPositionsPanel'
import { LpRemoveModal } from './LpRemoveModal'
import styles from './PoolsWidget.module.css'

type Toast = { status: 'success' | 'error' | 'info'; message: string } | null

// Предзаполнение диапазона при выборе пула: текущая цена ±5%.
const RANGE_SPREAD = 0.05

export function PoolsWidget() {
  const poolsQuery = usePools()
  const positionsQuery = useLpPositions()
  const addM = useAddLp()
  const removeM = useRemoveLp()

  const pools = poolsQuery.data ?? []
  const positions = positionsQuery.data?.positions ?? []

  const [selected, setSelected] = useState<string | null>(null)
  const [amount0, setAmount0] = useState('')
  const [amount1, setAmount1] = useState('')
  const [priceLower, setPriceLower] = useState('')
  const [priceUpper, setPriceUpper] = useState('')
  const [slippage, setSlippage] = useState('1')
  // Оплата всегда идёт в WETH (ERC-20).
  const useNativeEth = false
  const [removeTarget, setRemoveTarget] = useState<LpPosition | null>(null)
  const [toast, setToast] = useState<Toast>(null)

  const pool = pools.find((p) => p.poolAddress === selected) ?? null

  function handleSelect(poolAddress: string) {
    setSelected(poolAddress)
    const next = pools.find((p) => p.poolAddress === poolAddress)
    // Предзаполняем диапазон ±5% от текущей цены (юзер может поправить вручную).
    if (next) {
      setPriceLower((next.currentPrice * (1 - RANGE_SPREAD)).toFixed(2))
      setPriceUpper((next.currentPrice * (1 + RANGE_SPREAD)).toFixed(2))
    }
    setAmount0('')
    setAmount1('')
  }

  // Когда пулы загрузились, автоматически выбираем первый, если ничего не выбрано.
  useEffect(() => {
    if (!selected && pools.length > 0) {
      handleSelect(pools[0].poolAddress)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [pools, selected])

  // Дебаунсим вход квоты, чтобы не дёргать /lp/quote на каждый символ.
  const dAmount0 = useDebounce(amount0, 400)
  const dAmount1 = useDebounce(amount1, 400)
  const dPriceLower = useDebounce(priceLower, 400)
  const dPriceUpper = useDebounce(priceUpper, 400)
  const dSlippage = useDebounce(slippage, 400)

  const quoteInput = useMemo<LpDepositInput | null>(() => {
    if (!pool) return null
    const slippageNum = parseFloat(dSlippage)
    return {
      pool,
      amount0Human: dAmount0,
      amount1Human: dAmount1,
      priceLower: parseFloat(dPriceLower) || 0,
      priceUpper: parseFloat(dPriceUpper) || 0,
      slippageBps: Number.isFinite(slippageNum) ? Math.round(slippageNum * 100) : undefined,
      useNativeEth,
    }
  }, [pool, dAmount0, dAmount1, dPriceLower, dPriceUpper, dSlippage, useNativeEth])

  const quoteQuery = useLpQuote(quoteInput)

  function handleSubmit() {
    if (!pool) return
    const slippageNum = parseFloat(slippage)
    const input: LpDepositInput = {
      pool,
      amount0Human: amount0,
      amount1Human: amount1,
      priceLower: parseFloat(priceLower) || 0,
      priceUpper: parseFloat(priceUpper) || 0,
      slippageBps: Number.isFinite(slippageNum) ? Math.round(slippageNum * 100) : undefined,
      useNativeEth,
    }
    // Транзакция подтверждается в сети не мгновенно — предупреждаем юзера о возможном ожидании.
    setToast({ status: 'info', message: 'Внесение в пул может занять несколько минут…' })
    addM.mutate(input, {
      onSuccess: () => {
        setToast({ status: 'success', message: `Депозит в пул ${displaySymbol(pool.symbol0)}/${displaySymbol(pool.symbol1)} выполнен` })
        setAmount0('')
        setAmount1('')
      },
      onError: (e) => setToast({ status: 'error', message: getPoolsErrorMessage(e) }),
    })
  }

  function handleConfirmRemove(percent: number) {
    if (!removeTarget) return
    removeM.mutate(
      { tokenId: removeTarget.tokenId, percent },
      {
        onSuccess: () => {
          setRemoveTarget(null)
          setToast({ status: 'success', message: 'Ликвидность выведена на кошелёк' })
        },
        onError: (e) => setToast({ status: 'error', message: getPoolsErrorMessage(e) }),
      }
    )
  }

  return (
    <div className={styles.widget}>
      <PoolsTable
        pools={pools}
        selected={selected}
        onSelect={handleSelect}
        loading={poolsQuery.isLoading}
        error={poolsQuery.isError ? getPoolsErrorMessage(poolsQuery.error) : null}
      />

      <div className={styles.grid}>
        <LpDepositCard
          pool={pool}
          quote={quoteQuery.data}
          quoteFetching={quoteQuery.isFetching}
          pending={addM.isPending}
          amount0={amount0}
          amount1={amount1}
          priceLower={priceLower}
          priceUpper={priceUpper}
          slippage={slippage}
          onAmount0Change={setAmount0}
          onAmount1Change={setAmount1}
          onPriceLowerChange={setPriceLower}
          onPriceUpperChange={setPriceUpper}
          onSlippageChange={setSlippage}
          onSubmit={handleSubmit}
        />
        <LpPositionsPanel
          positions={positions}
          onRemove={(tokenId) => setRemoveTarget(positions.find((p) => p.tokenId === tokenId) ?? null)}
          removePending={removeM.isPending}
          isLoading={positionsQuery.isLoading}
          error={positionsQuery.isError ? getPoolsErrorMessage(positionsQuery.error) : null}
        />
      </div>

      {removeTarget && (
        <LpRemoveModal
          position={removeTarget}
          pending={removeM.isPending}
          onConfirm={handleConfirmRemove}
          onClose={() => setRemoveTarget(null)}
        />
      )}

      {toast && <Notification status={toast.status} message={toast.message} onClose={() => setToast(null)} />}
    </div>
  )
}
