/**
 * LP 交易处理 Hook
 * 集中管理所有交易逻辑
 */

import { useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { useWriteContract, useWaitForTransactionReceipt } from 'wagmi'
import { useTransactions } from '@/context/TransactionContext'
import type { TransactionType } from '@/context/TransactionContext'
import { useToast } from '../Toast'

interface TransactionCallbacks {
  onSuccess?: () => void
  onError?: (error: string) => void
}

export function useLPTransactions(callbacks?: TransactionCallbacks) {
  const { t } = useTranslation()
  const { addTransaction, updateTransaction } = useTransactions()
  const { showToast } = useToast()
  const pendingTxRef = useRef<{ id: string; type: TransactionType; amount?: string } | null>(null)

  // 使用 ref 存储 callbacks，避免作为依赖项
  const callbacksRef = useRef(callbacks)
  callbacksRef.current = callbacks

  const { writeContract, data: hash, isPending, error: writeError, reset, status: writeStatus } = useWriteContract()

  const { isLoading: isConfirming, isSuccess, isError, error: txError } = useWaitForTransactionReceipt({
    hash,
  })

  // 使用 ref 追踪已处理的状态，防止重复触发
  const processedHashRef = useRef<string | null>(null)
  const successProcessedRef = useRef(false)
  const errorProcessedRef = useRef(false)
  const writeErrorProcessedRef = useRef<Error | null>(null)

  // 超时自动重置机制
  useEffect(() => {
    let timeoutId: NodeJS.Timeout | null = null
    if (isPending && !hash) {
      timeoutId = setTimeout(() => {
        console.log('Transaction timeout, resetting state...')
        if (pendingTxRef.current) {
          updateTransaction(pendingTxRef.current.id, { status: 'failed', error: 'Transaction timeout' })
          pendingTxRef.current = null
        }
        showToast('error', t('toast.txTimeout') || 'Transaction timeout')
        reset()
      }, 30000)
    }
    return () => {
      if (timeoutId) clearTimeout(timeoutId)
    }
  }, [isPending, hash, t, showToast, reset, updateTransaction])

  // 处理交易提交
  useEffect(() => {
    if (hash && typeof hash === 'string' && hash.startsWith('0x') && pendingTxRef.current) {
      // 防止重复处理
      if (processedHashRef.current === hash) return
      processedHashRef.current = hash
      updateTransaction(pendingTxRef.current.id, { hash, status: 'pending' })
      showToast('info', t('toast.txSubmitted'))
    }
  }, [hash, t, showToast, updateTransaction])

  // 处理交易成功
  useEffect(() => {
    if (isSuccess && !successProcessedRef.current) {
      successProcessedRef.current = true
      if (pendingTxRef.current) {
        updateTransaction(pendingTxRef.current.id, { status: 'success' })
        showToast('success', t('toast.txSuccess'))
        pendingTxRef.current = null
      }
      callbacksRef.current?.onSuccess?.()
      reset()
      // 重置标记
      processedHashRef.current = null
      successProcessedRef.current = false
    }
  }, [isSuccess, t, showToast, updateTransaction, reset])

  // 处理交易失败
  useEffect(() => {
    if (isError && pendingTxRef.current && !errorProcessedRef.current) {
      errorProcessedRef.current = true
      const errorMsg = typeof txError?.message === 'string' ? txError.message : 'Transaction failed'
      updateTransaction(pendingTxRef.current.id, { status: 'failed', error: errorMsg })
      showToast('error', t('toast.txFailed'))
      pendingTxRef.current = null
      callbacksRef.current?.onError?.(errorMsg)
      reset()
      processedHashRef.current = null
      // 延迟重置
      setTimeout(() => { errorProcessedRef.current = false }, 100)
    }
  }, [isError, txError, t, showToast, updateTransaction, reset])

  // 处理写入错误
  useEffect(() => {
    if (writeError && writeErrorProcessedRef.current !== writeError) {
      writeErrorProcessedRef.current = writeError
      const errorMsg = parseError(writeError, t)
      showToast('error', errorMsg)
      if (pendingTxRef.current) {
        updateTransaction(pendingTxRef.current.id, { status: 'failed', error: errorMsg })
        pendingTxRef.current = null
      }
      callbacksRef.current?.onError?.(errorMsg)
      reset()
      processedHashRef.current = null
    }
  }, [writeError, t, showToast, updateTransaction, reset])

  // 错误解析
  const parseError = (error: any, t: any): string => {
    let msg = 'Unknown error'
    if (typeof error === 'string') {
      msg = error
    } else if (error?.shortMessage) {
      msg = error.shortMessage
    } else if (typeof error?.message === 'string') {
      msg = error.message
    } else if (error?.message) {
      msg = JSON.stringify(error.message)
    } else if (error) {
      try { msg = JSON.stringify(error) } catch { msg = String(error) }
    }

    if (msg.includes('User rejected') || msg.includes('user rejected')) {
      return t('toast.userRejected')
    }
    if (msg.includes('insufficient funds') || msg.includes('InsufficientBalance') || msg.includes('less than block base fee')) {
      return t('toast.insufficientBalance') + ' (Gas)'
    }
    if (msg.includes('CooldownNotPassed')) {
      return t('lp.cooldownNotPassed')
    }
    if (msg.includes('InsufficientOutput')) {
      return t('lp.insufficientOutput')
    }
    const match = msg.match(/error[:\s]+(\w+)/i)
    if (match) return match[1]
    return msg.slice(0, 100)
  }

  // 记录交易
  const recordTx = (type: TransactionType, amount?: string, token?: string) => {
    const id = addTransaction({
      type,
      hash: '',
      status: 'pending',
      amount,
      token,
    })
    pendingTxRef.current = { id, type, amount }
  }

  // 计算按钮是否应该禁用
  const isProcessing = (isPending || isConfirming) && writeStatus !== 'error'

  return {
    writeContract,
    recordTx,
    isProcessing,
    isPending,
    isConfirming,
    hash,
    reset,
  }
}

export { parseError }

function parseError(error: any, t: any): string {
  let msg = 'Unknown error'
  if (typeof error === 'string') {
    msg = error
  } else if (error?.shortMessage) {
    msg = error.shortMessage
  } else if (typeof error?.message === 'string') {
    msg = error.message
  } else if (error?.message) {
    msg = JSON.stringify(error.message)
  } else if (error) {
    try { msg = JSON.stringify(error) } catch { msg = String(error) }
  }

  if (msg.includes('User rejected') || msg.includes('user rejected')) {
    return t('toast.userRejected')
  }
  if (msg.includes('insufficient funds') || msg.includes('InsufficientBalance') || msg.includes('less than block base fee')) {
    return t('toast.insufficientBalance') + ' (Gas)'
  }
  if (msg.includes('CooldownNotPassed')) {
    return t('lp.cooldownNotPassed')
  }
  if (msg.includes('InsufficientOutput')) {
    return t('lp.insufficientOutput')
  }
  const match = msg.match(/error[:\s]+(\w+)/i)
  if (match) return match[1]
  return msg.slice(0, 100)
}
