/**
 * ENS Utilities - Enhanced ENS name support
 */

import { isAddress } from 'viem'
import { getPublicClient } from '@wagmi/core'
import { config } from '../config/wagmi'
import { mainnet } from 'wagmi/chains'
import { validateAddress } from './security'

type EnsPublicClient = {
  getEnsName: (args: { address: `0x${string}` }) => Promise<string | null>
  getEnsAddress: (args: { name: string }) => Promise<string | null>
}

const ENS_CACHE: Record<string, { name: string | null; timestamp: number }> = {}
const ADDRESS_CACHE: Record<string, { address: string | null; timestamp: number }> = {}
const CACHE_TTL = 3600000 // 1 hour

export async function resolveENS(address: string): Promise<string | null> {
  if (!isAddress(address)) return null

  // Check cache
  const cached = ENS_CACHE[address.toLowerCase()]
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.name
  }

  try {
    // Only resolve on mainnet
    const publicClient = getPublicClient(
      config as never,
      { chainId: mainnet.id } as never
    ) as EnsPublicClient | undefined
    if (!publicClient) {
      return null
    }

    const name = await publicClient.getEnsName({ address: address as `0x${string}` })

    ENS_CACHE[address.toLowerCase()] = {
      name,
      timestamp: Date.now(),
    }

    return name
  } catch (error) {
    console.error('ENS resolution error:', error)
    // Cache null result to avoid repeated failed attempts
    ENS_CACHE[address.toLowerCase()] = {
      name: null,
      timestamp: Date.now(),
    }
    return null
  }
}

export async function resolveAddress(name: string): Promise<string | null> {
  if (!name.endsWith('.eth')) return null

  // Check cache
  const cached = ADDRESS_CACHE[name.toLowerCase()]
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.address
  }

  try {
    // Only resolve on mainnet
    const publicClient = getPublicClient(
      config as never,
      { chainId: mainnet.id } as never
    ) as EnsPublicClient | undefined
    if (!publicClient) {
      return null
    }

    const address = await publicClient.getEnsAddress({ name })

    ADDRESS_CACHE[name.toLowerCase()] = {
      address,
      timestamp: Date.now(),
    }

    return address
  } catch (error) {
    console.error('ENS address resolution error:', error)
    // Cache null result
    ADDRESS_CACHE[name.toLowerCase()] = {
      address: null,
      timestamp: Date.now(),
    }
    return null
  }
}

export function clearENSCache(): void {
  Object.keys(ENS_CACHE).forEach((key) => delete ENS_CACHE[key])
}

export function isEnsName(input: string): boolean {
  const trimmed = input.trim().toLowerCase()
  return trimmed.endsWith('.eth') && trimmed.length > 4 && !trimmed.includes(' ')
}

/** Resolve `.eth` via mainnet ENS or validate hex address. */
export async function resolveAddressOrHex(input: string): Promise<{
  valid: boolean
  error?: string
  checksummed?: string
}> {
  const trimmed = input.trim()
  if (!trimmed) {
    return { valid: false, error: 'Address or ENS name required' }
  }

  if (isEnsName(trimmed)) {
    const resolved = await resolveAddress(trimmed)
    if (!resolved) {
      return { valid: false, error: `Could not resolve ENS name: ${trimmed}` }
    }
    return validateAddress(resolved)
  }

  return validateAddress(trimmed)
}
