import { useEffect, useMemo, useState } from 'react'
import { Card } from '@/libs/frontend-ui-primitives'
import { DetailRow } from '@/components/common/DetailRow'
import EntityBadge from '@/components/common/EntityBadge'
import type { ContractProfile } from '@/services/api/contracts'
import { fetchEip712DomainDecoded, type DecodedEip712Domain } from '@/services/api/eip712Domain'

function hasMethod(profile: ContractProfile | null | undefined, name: string): boolean {
  if (!profile) return false
  const all = [...(profile.read_methods || []), ...(profile.write_methods || [])]
  return all.some((m) => m.name === name)
}

const ERC5267_EXPLANATION =
  'ERC-5267 defines eip712Domain() so wallets and relayers can discover the EIP-712 signing domain without guessing types or replay parameters.'

export default function TokenSigningSurfaceCard({
  address,
  contractProfile,
}: {
  address: string
  contractProfile: ContractProfile | null
}) {
  const [domain, setDomain] = useState<DecodedEip712Domain | null>(null)
  const [domainError, setDomainError] = useState<string | null>(null)

  const abiHasEip712Domain = hasMethod(contractProfile, 'eip712Domain')

  useEffect(() => {
    if (!abiHasEip712Domain) {
      setDomain(null)
      setDomainError(null)
      return
    }
    let cancelled = false
    setDomainError(null)
    void (async () => {
      try {
        const decoded = await fetchEip712DomainDecoded(address)
        if (!cancelled) {
          setDomain(decoded)
          if (!decoded) setDomainError('eip712Domain() is present in the ABI but the live call did not return decodable data (proxy, revert, or RPC).')
        }
      } catch (e) {
        if (!cancelled) {
          setDomain(null)
          setDomainError(e instanceof Error ? e.message : 'Failed to read eip712Domain.')
        }
      }
    })()
    return () => {
      cancelled = true
    }
  }, [address, abiHasEip712Domain])

  const standards = useMemo(
    () => [
      {
        id: 'ERC-20',
        detected:
          hasMethod(contractProfile, 'name') ||
          hasMethod(contractProfile, 'symbol') ||
          hasMethod(contractProfile, 'decimals') ||
          hasMethod(contractProfile, 'totalSupply'),
        note: 'Standard fungible token interface expected by explorers and wallets.',
      },
      {
        id: 'EIP-712',
        detected: hasMethod(contractProfile, 'DOMAIN_SEPARATOR') || abiHasEip712Domain,
        note: 'Typed structured data hashing for signatures.',
      },
      {
        id: 'ERC-2612',
        detected: hasMethod(contractProfile, 'permit') || hasMethod(contractProfile, 'nonces'),
        note: 'Permit-style allowance via signature.',
      },
      {
        id: 'ERC-3009',
        detected:
          hasMethod(contractProfile, 'authorizationState') ||
          hasMethod(contractProfile, 'transferWithAuthorization') ||
          hasMethod(contractProfile, 'receiveWithAuthorization'),
        note: 'Transfer authorization without prior allowance.',
      },
      {
        id: 'ERC-5267',
        detected: abiHasEip712Domain,
        note: ERC5267_EXPLANATION,
      },
    ],
    [contractProfile, abiHasEip712Domain],
  )

  const verificationMeta = useMemo(() => {
    if (!contractProfile) return []
    const rows: { label: string; value: string }[] = []
    if (contractProfile.contract_name) rows.push({ label: 'Verified name', value: contractProfile.contract_name })
    if (contractProfile.compiler_version) rows.push({ label: 'Compiler', value: contractProfile.compiler_version })
    if (contractProfile.license_type) rows.push({ label: 'License', value: contractProfile.license_type })
    if (contractProfile.evm_version) rows.push({ label: 'EVM version', value: contractProfile.evm_version })
    if (contractProfile.optimization_enabled != null) {
      rows.push({
        label: 'Optimization',
        value: `${contractProfile.optimization_enabled ? 'On' : 'Off'}${contractProfile.optimization_runs != null ? ` · ${contractProfile.optimization_runs} runs` : ''}`,
      })
    }
    if (contractProfile.source_status_text) rows.push({ label: 'Source status', value: contractProfile.source_status_text })
    return rows
  }, [contractProfile])

  if (!contractProfile) {
    return (
      <Card title="Signing surface & verification metadata">
        <p className="text-sm text-gray-600 dark:text-gray-400">
          Contract ABI and verification metadata were not available. Open the contract address page after Blockscout indexes this token, or verify the contract on the explorer.
        </p>
      </Card>
    )
  }

  return (
    <Card title="Signing surface & verification metadata">
      <dl className="space-y-4">
        <DetailRow label="ABI coverage" valueClassName="flex flex-wrap gap-2">
          <EntityBadge label={contractProfile.abi_available ? 'ABI available' : 'ABI unavailable'} tone={contractProfile.abi_available ? 'success' : 'warning'} />
          <EntityBadge label={contractProfile.source_verified ? 'Source verified' : 'Source not verified'} tone={contractProfile.source_verified ? 'success' : 'warning'} />
        </DetailRow>

        <DetailRow label="ERC-5267 (EIP-712 domain introspection)" valueClassName="space-y-3">
          <div className="flex flex-wrap gap-2">
            <EntityBadge
              label={abiHasEip712Domain ? 'eip712Domain() in ABI' : 'eip712Domain() not in ABI'}
              tone={abiHasEip712Domain ? 'success' : 'warning'}
            />
            {domain ? <EntityBadge label="Live domain decoded" tone="success" /> : null}
          </div>
          <p className="text-sm text-gray-600 dark:text-gray-400">{ERC5267_EXPLANATION}</p>
          {domain ? (
            <div className="grid gap-3 sm:grid-cols-2">
              <div className="rounded-xl border border-gray-200 bg-gray-50 p-3 text-sm dark:border-gray-700 dark:bg-gray-900/40">
                <div className="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Domain fields</div>
                <dl className="mt-2 space-y-1.5 text-gray-900 dark:text-white">
                  <div><span className="text-gray-500 dark:text-gray-400">fields </span>{domain.fields}</div>
                  <div><span className="text-gray-500 dark:text-gray-400">name </span>{domain.name || '—'}</div>
                  <div><span className="text-gray-500 dark:text-gray-400">version </span>{domain.version || '—'}</div>
                  <div><span className="text-gray-500 dark:text-gray-400">chainId </span>{domain.chainId}</div>
                  <div className="break-all">
                    <span className="text-gray-500 dark:text-gray-400">verifyingContract </span>
                    {domain.verifyingContract}
                  </div>
                  <div className="break-all">
                    <span className="text-gray-500 dark:text-gray-400">salt </span>
                    {domain.salt}
                  </div>
                  <div className="break-all">
                    <span className="text-gray-500 dark:text-gray-400">extensions </span>
                    {domain.extensionsSummary}
                  </div>
                </dl>
              </div>
            </div>
          ) : abiHasEip712Domain && domainError ? (
            <p className="text-sm text-amber-700 dark:text-amber-300">{domainError}</p>
          ) : !abiHasEip712Domain ? (
            <p className="text-sm text-gray-600 dark:text-gray-400">
              This contract’s verified ABI does not expose eip712Domain(). ERC-5267 introspection is unavailable from the explorer surface until the implementation adds it.
            </p>
          ) : null}
        </DetailRow>

        <DetailRow label="Related interfaces" valueClassName="flex flex-wrap gap-2">
          {standards
            .filter((s) => s.id !== 'ERC-5267')
            .map((s) => (
              <EntityBadge
                key={s.id}
                label={`${s.id} ${s.detected ? 'detected' : 'not detected'}`}
                tone={s.detected ? 'success' : 'warning'}
                className="normal-case tracking-normal"
              />
            ))}
        </DetailRow>

        {verificationMeta.length > 0 ? (
          <DetailRow label="Verification metadata">
            <div className="grid gap-3 sm:grid-cols-2">
              {verificationMeta.map((row) => (
                <div key={row.label} className="rounded-xl border border-gray-200 bg-gray-50 p-3 text-sm dark:border-gray-700 dark:bg-gray-900/40">
                  <div className="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">{row.label}</div>
                  <div className="mt-2 break-words text-gray-900 dark:text-white">{row.value}</div>
                </div>
              ))}
            </div>
          </DetailRow>
        ) : (
          <DetailRow label="Verification metadata">
            <span className="text-sm text-gray-600 dark:text-gray-400">No compiler or naming metadata was returned with this contract record.</span>
          </DetailRow>
        )}

        <DetailRow label="Interpretation">
          <div className="space-y-3">
            {standards.map((s) => (
              <div key={s.id} className="rounded-xl border border-gray-200 bg-gray-50 p-3 text-sm dark:border-gray-700 dark:bg-gray-900/40">
                <div className="flex flex-wrap items-center gap-2">
                  <span className="font-medium text-gray-900 dark:text-white">{s.id}</span>
                  <EntityBadge label={s.detected ? 'detected' : 'not detected'} tone={s.detected ? 'success' : 'warning'} />
                </div>
                <p className="mt-2 text-gray-600 dark:text-gray-400">{s.note}</p>
              </div>
            ))}
          </div>
        </DetailRow>
      </dl>
    </Card>
  )
}
