import type { GetServerSideProps } from 'next'
import Link from 'next/link'
import { useEffect, useMemo, useState } from 'react'
import { useRouter } from 'next/router'
import { Card, Address } from '@/libs/frontend-ui-primitives'
import { transactionsApi, Transaction } from '@/services/api/transactions'
import { readWatchlistFromStorage } from '@/utils/watchlist'
import PageIntro from '@/components/common/PageIntro'
import ExplorerFreshnessDisclosure from '@/components/common/ExplorerFreshnessDisclosure'
import SectionTabs, { TabPanel, type SectionTab } from '@/components/common/SectionTabs'
import { fetchPublicJson } from '@/utils/publicExplorer'
import { statsApi } from '@/services/api/stats'
import { missionControlApi } from '@/services/api/missionControl'
import { isEnsName, resolveEnsAddress } from '@/utils/ens'
import { resolveAddressFromRegistryEns } from '@/utils/web3IdentityRegistry'
import { summarizeChainActivity } from '@/utils/activityContext'
import type { ExplorerStats } from '@/services/api/stats'
import type { MissionControlBridgeStatusResponse } from '@/services/api/missionControl'
import { resolveEffectiveFreshness } from '@/utils/explorerFreshness'

function normalizeAddress(value: string) {
  const trimmed = value.trim()
  return /^0x[a-fA-F0-9]{40}$/.test(trimmed) ? trimmed : ''
}

function canOpenAddressQuery(value: string) {
  const trimmed = value.trim()
  return Boolean(normalizeAddress(trimmed) || isEnsName(trimmed))
}

interface AddressesPageProps {
  initialRecentTransactions: Transaction[]
  initialLatestBlocks: Array<{ number: number; timestamp: string }>
  initialStats: ExplorerStats | null
  initialBridgeStatus: MissionControlBridgeStatusResponse | null
}

export default function AddressesPage({
  initialRecentTransactions,
  initialLatestBlocks,
  initialStats,
  initialBridgeStatus,
}: AddressesPageProps) {
  const router = useRouter()
  const chainId = parseInt(process.env.NEXT_PUBLIC_CHAIN_ID || '138')
  const [query, setQuery] = useState('')
  const [recentTransactions, setRecentTransactions] = useState<Transaction[]>(initialRecentTransactions)
  const [latestBlocks, setLatestBlocks] = useState(initialLatestBlocks)
  const [stats, setStats] = useState<ExplorerStats | null>(initialStats)
  const [bridgeStatus, setBridgeStatus] = useState<MissionControlBridgeStatusResponse | null>(initialBridgeStatus)
  const [watchlist, setWatchlist] = useState<string[]>([])
  const activityContext = useMemo(
    () =>
      summarizeChainActivity({
        blocks: latestBlocks.map((block) => ({
          chain_id: chainId,
          number: block.number,
          hash: '',
          timestamp: block.timestamp,
          miner: '',
          transaction_count: 0,
          gas_used: 0,
          gas_limit: 0,
        })),
        transactions: recentTransactions,
        latestBlockNumber: latestBlocks[0]?.number ?? null,
        latestBlockTimestamp: latestBlocks[0]?.timestamp ?? null,
        freshness: resolveEffectiveFreshness(stats, bridgeStatus),
        diagnostics: stats?.diagnostics ?? bridgeStatus?.data?.diagnostics ?? null,
      }),
    [chainId, bridgeStatus, latestBlocks, stats, recentTransactions],
  )

  useEffect(() => {
    if (initialRecentTransactions.length > 0) {
      setRecentTransactions(initialRecentTransactions)
      return
    }

    let active = true
    transactionsApi.listSafe(chainId, 1, 20)
      .then(({ ok, data }) => {
        if (active && ok) {
          setRecentTransactions(data)
        }
      })
      .catch(() => {
        if (active) {
          setRecentTransactions([])
        }
      })
    return () => {
      active = false
    }
  }, [chainId, initialRecentTransactions])

  useEffect(() => {
    if (initialStats && initialBridgeStatus && initialLatestBlocks.length > 0) {
      setStats(initialStats)
      setBridgeStatus(initialBridgeStatus)
      setLatestBlocks(initialLatestBlocks)
      return
    }

    let active = true

    Promise.allSettled([
      statsApi.get().catch(() => null),
      missionControlApi.getBridgeStatus().catch(() => null),
      fetchPublicJson<{ items?: Array<{ height?: number | string | null; timestamp?: string | null }> }>(
        '/api/v2/blocks?page=1&page_size=3',
      ).catch(() => null),
    ]).then(([statsResult, bridgeResult, blocksResult]) => {
      if (!active) return
      if (statsResult.status === 'fulfilled' && statsResult.value) {
        setStats(statsResult.value)
      }
      if (bridgeResult.status === 'fulfilled' && bridgeResult.value) {
        setBridgeStatus(bridgeResult.value)
      }
      if (blocksResult.status === 'fulfilled' && Array.isArray(blocksResult.value?.items)) {
        setLatestBlocks(
          blocksResult.value.items
            .map((item) => ({
              number: Number(item.height || 0),
              timestamp: item.timestamp || '',
            }))
            .filter((item) => Number.isFinite(item.number) && item.number > 0 && item.timestamp),
        )
      }
    })

    return () => {
      active = false
    }
  }, [initialBridgeStatus, initialLatestBlocks, initialStats])

  useEffect(() => {
    if (typeof window === 'undefined') {
      return
    }

    try {
      setWatchlist(readWatchlistFromStorage(window.localStorage))
    } catch {
      setWatchlist([])
    }
  }, [])

  const activeAddresses = useMemo(() => {
    const seen = new Set<string>()
    const addresses: string[] = []

    for (const tx of recentTransactions) {
      for (const candidate of [tx.from_address, tx.to_address]) {
        if (!candidate) continue
        const normalized = candidate.toLowerCase()
        if (seen.has(normalized)) continue
        seen.add(normalized)
        addresses.push(candidate)
        if (addresses.length >= 8) return addresses
      }
    }

    return addresses
  }, [recentTransactions])

  const [opening, setOpening] = useState(false)
  const [listTab, setListTab] = useState<'watchlist' | 'recent'>('watchlist')

  const addressListTabs = useMemo<SectionTab<'watchlist' | 'recent'>[]>(
    () => [
      { id: 'watchlist', label: 'Watchlist', count: watchlist.length },
      { id: 'recent', label: 'Recently active', count: activeAddresses.length },
    ],
    [activeAddresses.length, watchlist.length],
  )

  const handleOpenAddress = async (event: React.FormEvent) => {
    event.preventDefault()
    const trimmed = query.trim()
    if (!trimmed) return

    const normalized = normalizeAddress(trimmed)
    if (normalized) {
      router.push(`/addresses/${normalized}`)
      return
    }

    if (!isEnsName(trimmed)) return

    setOpening(true)
    try {
      const fromRegistry = resolveAddressFromRegistryEns(trimmed)
      const resolved = fromRegistry || (await resolveEnsAddress(trimmed))
      if (resolved) {
        router.push(`/addresses/${resolved}`)
      }
    } finally {
      setOpening(false)
    }
  }

  return (
    <div className="container mx-auto px-4 py-4 sm:py-6">
      <PageIntro
        compact
        eyebrow="Address Discovery"
        title="Addresses"
        description="Open any Chain 138 address, resolve ENS names, or browse watchlist and recent activity."
        actions={[
          { href: '/watchlist', label: 'Watchlist' },
          { href: '/search', label: 'Search' },
        ]}
      />

      <ExplorerFreshnessDisclosure
        context={activityContext}
        stats={stats}
        bridgeStatus={bridgeStatus}
        activityTitle="Recent activity"
        scopeLabel="Recently active addresses come from indexed transactions."
      />

      <Card className="mb-4" title="Open address">
        <form onSubmit={handleOpenAddress} className="flex flex-col gap-3 sm:flex-row">
          <input
            type="text"
            value={query}
            onChange={(event) => setQuery(event.target.value)}
            placeholder="0x… or name.eth"
            className="flex-1 rounded-lg border border-gray-300 px-4 py-2 focus:outline-none focus:ring-2 focus:ring-primary-500 dark:border-gray-700 dark:bg-gray-900"
          />
          <button
            type="submit"
            disabled={!canOpenAddressQuery(query) || opening}
            className="rounded-lg bg-primary-600 px-6 py-2 text-white hover:bg-primary-700 disabled:cursor-not-allowed disabled:opacity-50"
          >
            {opening ? 'Resolving…' : 'Open'}
          </button>
        </form>
      </Card>

      <SectionTabs
        tabs={addressListTabs}
        activeTab={listTab}
        onChange={setListTab}
        idPrefix="addresses-list"
        ariaLabel="Address lists"
        className="-mx-4 mb-3 px-4"
      />

      <TabPanel idPrefix="addresses-list" tabId="watchlist" activeTab={listTab}>
        <Card title="Saved watchlist">
          {watchlist.length === 0 ? (
            <p className="text-sm text-gray-600 dark:text-gray-400">
              No saved addresses yet. Add entries from address detail pages.
            </p>
          ) : (
            <div className="space-y-2">
              {watchlist.map((entry) => (
                <Link key={entry} href={`/addresses/${entry}`} className="block text-primary-600 hover:underline">
                  <Address address={entry} showCopy={false} />
                </Link>
              ))}
              <Link href="/watchlist" className="inline-block pt-2 text-sm text-primary-600 hover:underline">
                Full watchlist →
              </Link>
            </div>
          )}
        </Card>
      </TabPanel>

      <TabPanel idPrefix="addresses-list" tabId="recent" activeTab={listTab}>
        <Card title="Recently active">
          {activeAddresses.length === 0 ? (
            <p className="text-sm text-gray-600 dark:text-gray-400">
              No recent address activity in the visible transaction sample.
            </p>
          ) : (
            <div className="space-y-2">
              {activeAddresses.map((entry) => (
                <Link key={entry} href={`/addresses/${entry}`} className="block text-primary-600 hover:underline">
                  <Address address={entry} showCopy={false} />
                </Link>
              ))}
            </div>
          )}
        </Card>
      </TabPanel>
    </div>
  )
}

export const getServerSideProps: GetServerSideProps<AddressesPageProps> = async () => ({
  props: {
    initialRecentTransactions: [],
    initialLatestBlocks: [],
    initialStats: null,
    initialBridgeStatus: null,
  },
})
