/**
 * useWeb3Wallet Hook
 *
 * Manages MetaMask wallet connection and account state.
 *
 * Features:
 * - Connect/disconnect wallet
 * - Listen for account changes
 * - Listen for network changes
 * - Link wallet address to backend user account
 *
 * NOTE: This is pseudocode/skeleton showing the architecture.
 * In production, you would use wagmi, ethers.js, or web3.js libraries.
 */

import { useState, useEffect, useCallback } from 'react'

interface Web3WalletState {
  walletAddress: string | null
  chainId: number | null
  isConnected: boolean
  isConnecting: boolean
  error: string | null
}

interface Web3WalletHook extends Web3WalletState {
  connectWallet: () => Promise<void>
  disconnectWallet: () => void
  switchNetwork: (chainId: number) => Promise<void>
}

// Declare window.ethereum type
declare global {
  interface Window {
    ethereum?: {
      request: (args: { method: string; params?: any[] }) => Promise<any>
      on: (event: string, callback: (...args: any[]) => void) => void
      removeListener: (event: string, callback: (...args: any[]) => void) => void
      selectedAddress: string | null
    }
  }
}

export const useWeb3Wallet = (): Web3WalletHook => {
  const [state, setState] = useState<Web3WalletState>({
    walletAddress: null,
    chainId: null,
    isConnected: false,
    isConnecting: false,
    error: null,
  })

  /**
   * Check if MetaMask is installed
   */
  const isMetaMaskInstalled = useCallback(() => {
    return typeof window !== 'undefined' && typeof window.ethereum !== 'undefined'
  }, [])

  /**
   * Connect to MetaMask wallet
   */
  const connectWallet = useCallback(async () => {
    if (!isMetaMaskInstalled()) {
      setState(prev => ({
        ...prev,
        error: 'Please install MetaMask to use blockchain features'
      }))
      return
    }

    setState(prev => ({ ...prev, isConnecting: true, error: null }))

    try {
      // Pseudocode: Request account access
      // const accounts = await window.ethereum!.request({
      //   method: 'eth_requestAccounts'
      // })

      // const address = accounts[0]

      // // Get current chain ID
      // const chainId = await window.ethereum!.request({
      //   method: 'eth_chainId'
      // })

      // setState({
      //   walletAddress: address,
      //   chainId: parseInt(chainId, 16),
      //   isConnected: true,
      //   isConnecting: false,
      //   error: null
      // })

      // // Link wallet to backend user account
      // await linkWalletToAccount(address)

      // console.log('Wallet connected:', address)

      // Placeholder for pseudocode
      const mockAddress = '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb'
      const mockChainId = 11155111 // Sepolia

      setState({
        walletAddress: mockAddress,
        chainId: mockChainId,
        isConnected: true,
        isConnecting: false,
        error: null
      })

      console.log('[Web3] Wallet connected:', mockAddress)
    } catch (error: any) {
      console.error('Failed to connect wallet:', error)
      setState(prev => ({
        ...prev,
        isConnecting: false,
        error: error.message || 'Failed to connect wallet'
      }))
    }
  }, [isMetaMaskInstalled])

  /**
   * Disconnect wallet
   */
  const disconnectWallet = useCallback(() => {
    setState({
      walletAddress: null,
      chainId: null,
      isConnected: false,
      isConnecting: false,
      error: null
    })
    console.log('[Web3] Wallet disconnected')
  }, [])

  /**
   * Switch to a different network
   */
  const switchNetwork = useCallback(async (targetChainId: number) => {
    if (!isMetaMaskInstalled()) {
      return
    }

    try {
      // Pseudocode: Switch network
      // await window.ethereum!.request({
      //   method: 'wallet_switchEthereumChain',
      //   params: [{ chainId: `0x${targetChainId.toString(16)}` }]
      // })

      console.log(`[Web3] Switched to chain ID: ${targetChainId}`)
    } catch (error: any) {
      // If network doesn't exist, add it
      if (error.code === 4902) {
        console.log('[Web3] Network not added, prompting user to add it')
        // Pseudocode: Add network
        // await window.ethereum!.request({
        //   method: 'wallet_addEthereumChain',
        //   params: [getNetworkConfig(targetChainId)]
        // })
      }
      console.error('Failed to switch network:', error)
    }
  }, [isMetaMaskInstalled])

  /**
   * Link wallet address to backend user account
   */
  const linkWalletToAccount = async (address: string) => {
    // Pseudocode: Call backend API
    // try {
    //   await fetch('/api/v1/users/link-wallet', {
    //     method: 'POST',
    //     headers: {
    //       'Content-Type': 'application/json',
    //       'Authorization': `Bearer ${getAccessToken()}`
    //     },
    //     body: JSON.stringify({ wallet_address: address })
    //   })
    //   console.log('[Web3] Wallet linked to user account')
    // } catch (error) {
    //   console.error('[Web3] Failed to link wallet:', error)
    // }

    console.log('[Web3] Wallet linked to account:', address)
  }

  /**
   * Listen for account changes
   */
  useEffect(() => {
    if (!isMetaMaskInstalled()) {
      return
    }

    const handleAccountsChanged = (accounts: string[]) => {
      if (accounts.length === 0) {
        // User disconnected
        disconnectWallet()
      } else if (accounts[0] !== state.walletAddress) {
        // User switched accounts
        setState(prev => ({
          ...prev,
          walletAddress: accounts[0]
        }))
        console.log('[Web3] Account changed to:', accounts[0])
      }
    }

    // Pseudocode: Add event listener
    // window.ethereum!.on('accountsChanged', handleAccountsChanged)

    // return () => {
    //   window.ethereum!.removeListener('accountsChanged', handleAccountsChanged)
    // }
  }, [isMetaMaskInstalled, state.walletAddress, disconnectWallet])

  /**
   * Listen for network changes
   */
  useEffect(() => {
    if (!isMetaMaskInstalled()) {
      return
    }

    const handleChainChanged = (chainId: string) => {
      const newChainId = parseInt(chainId, 16)
      setState(prev => ({
        ...prev,
        chainId: newChainId
      }))
      console.log('[Web3] Network changed to chain ID:', newChainId)

      // Refresh page on network change (recommended by MetaMask)
      // window.location.reload()
    }

    // Pseudocode: Add event listener
    // window.ethereum!.on('chainChanged', handleChainChanged)

    // return () => {
    //   window.ethereum!.removeListener('chainChanged', handleChainChanged)
    // }
  }, [isMetaMaskInstalled])

  /**
   * Check if already connected on mount
   */
  useEffect(() => {
    const checkConnection = async () => {
      if (!isMetaMaskInstalled()) {
        return
      }

      // Pseudocode: Check if already connected
      // const accounts = await window.ethereum!.request({
      //   method: 'eth_accounts'
      // })

      // if (accounts.length > 0) {
      //   const chainId = await window.ethereum!.request({
      //     method: 'eth_chainId'
      //   })

      //   setState({
      //     walletAddress: accounts[0],
      //     chainId: parseInt(chainId, 16),
      //     isConnected: true,
      //     isConnecting: false,
      //     error: null
      //   })
      // }
    }

    checkConnection()
  }, [isMetaMaskInstalled])

  return {
    ...state,
    connectWallet,
    disconnectWallet,
    switchNetwork,
  }
}

/**
 * Network configuration for wallet_addEthereumChain
 */
const getNetworkConfig = (chainId: number) => {
  const configs: Record<number, any> = {
    1: {
      chainId: '0x1',
      chainName: 'Ethereum Mainnet',
      nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
      rpcUrls: ['https://eth-mainnet.alchemyapi.io/v2/YOUR-API-KEY'],
      blockExplorerUrls: ['https://etherscan.io']
    },
    11155111: {
      chainId: '0xaa36a7',
      chainName: 'Sepolia Testnet',
      nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
      rpcUrls: ['https://rpc.sepolia.org'],
      blockExplorerUrls: ['https://sepolia.etherscan.io']
    },
    137: {
      chainId: '0x89',
      chainName: 'Polygon Mainnet',
      nativeCurrency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 },
      rpcUrls: ['https://polygon-rpc.com'],
      blockExplorerUrls: ['https://polygonscan.com']
    },
    80001: {
      chainId: '0x13881',
      chainName: 'Polygon Mumbai Testnet',
      nativeCurrency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 },
      rpcUrls: ['https://rpc-mumbai.maticvigil.com'],
      blockExplorerUrls: ['https://mumbai.polygonscan.com']
    }
  }

  return configs[chainId]
}
