import { useState } from 'react'
import { useDebounce } from '@shared/lib/hooks/useDebounce'
import { progressPercent } from '@entities/commission'
import { GAS_PRICE, MIN_RUB_AMOUNT } from '@shared/config/constants'
import type { ConvertFieldData } from '@shared/ui'
import { usePaymentConfig } from '../hooks/usePaymentConfig'
import { usePaymentQuote } from '../hooks/usePaymentQuote'
import { usePaymentQuoteByRub } from '../hooks/usePaymentQuoteByRub'

const TOO_LARGE_ERROR = 'Сумма слишком большая и превышает 600 000 ₽'

const sanitize = (raw: string) => raw.replace(/[^0-9.]/g, '')

interface Options {
  /** Значение курса USDT/RUB до загрузки конфига (пилюля). */
  rateFallback?: number
}

export function useCurrencyConversion({ rateFallback = 0 }: Options = {}) {
  const [direction, setDirection] = useState<'usdt_to_rub' | 'rub_to_usdt'>('usdt_to_rub')
  const [usdtInput, setUsdtInput] = useState('1000')
  const [rubInput, setRubInput] = useState(String(MIN_RUB_AMOUNT))

  const { data: config } = usePaymentConfig()
  const configUsdtRate = Number(config?.usdt_exchange_rate) || rateFallback
  const gasPriceRub = Number(config?.gas_fee) || GAS_PRICE

  const isUsdtToRub = direction === 'usdt_to_rub'

  const numUsdt = Number.parseFloat(usdtInput) || 0
  const debouncedUsdt = useDebounce(numUsdt, 400)
  const { data: quoteUsdtToRub, isError: quoteError } = usePaymentQuote(isUsdtToRub ? debouncedUsdt : 0)

  const numRubInput = Number.parseFloat(rubInput) || 0
  const debouncedRub = useDebounce(numRubInput, 400)
  const { data: quoteRubToUsdt, isError: quoteRubError } = usePaymentQuoteByRub(!isUsdtToRub ? debouncedRub : 0)

  const rubBelowMin = !isUsdtToRub && numRubInput > 0 && numRubInput < MIN_RUB_AMOUNT

  const rubTotal = quoteUsdtToRub?.total_price ?? ''
  const rubTotalNum = Number(rubTotal) || 0
  const usdtFromRub = quoteRubToUsdt?.usdt_amount ?? ''
  const usdtFromRubNum = Number(usdtFromRub) || 0

  const commission = isUsdtToRub
    ? Number(quoteUsdtToRub?.service_fee) || 0
    : Number(quoteRubToUsdt?.service_fee) || 0

  const displayRubAmount = isUsdtToRub ? rubTotalNum : numRubInput
  const effectiveRate = isUsdtToRub
    ? (numUsdt > 0 ? rubTotalNum / numUsdt : 0)
    : (usdtFromRubNum > 0 ? numRubInput / usdtFromRubNum : 0)

  function onSwap() {
    setDirection(d => (d === 'usdt_to_rub' ? 'rub_to_usdt' : 'usdt_to_rub'))
  }

  const convert: ConvertFieldData = isUsdtToRub
    ? {
        value: usdtInput,
        currency: 'USDT',
        onChange: (raw) => setUsdtInput(sanitize(raw)),
        error: quoteError ? TOO_LARGE_ERROR : undefined,
      }
    : {
        value: rubInput,
        currency: 'RUB',
        onChange: (raw) => setRubInput(sanitize(raw)),
        error: rubBelowMin
          ? `Минимальная сумма: ${MIN_RUB_AMOUNT.toLocaleString('ru-RU')} ₽`
          : quoteRubError
            ? TOO_LARGE_ERROR
            : undefined,
      }

  const pay: ConvertFieldData = isUsdtToRub
    ? { value: rubTotal, currency: 'RUB' }
    : { value: usdtFromRub, currency: 'USDT' }

  return {
    isUsdtToRub,
    gasPriceRub,
    configUsdtRate,
    convert,
    pay,
    onSwap,
    commission: {
      amount: displayRubAmount,
      progress: progressPercent(displayRubAmount),
      commission,
      effectiveRate,
    },
    // сырые значения для создания ордера и валидации в обёртках
    numUsdt,
    usdtFromRubNum,
    rubTotal,
    rubTotalNum,
    numRubInput,
    usdtFromRub,
    rubBelowMin,
  }
}
