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 { fetchPublicJson } from '@/utils/publicExplorer'
import { normalizeTransaction } from '@/services/api/blockscout'
import { summarizeChainActivity } from '@/utils/activityContext'
import ActivityContextPanel from '@/components/common/ActivityContextPanel'
import FreshnessTrustNote from '@/components/common/FreshnessTrustNote'
import { normalizeExplorerStats, 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 : ''
}

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

function serializeRecentTransactions(transactions: Transaction[]): Transaction[] {
  return JSON.parse(
    JSON.stringify(
      transactions.map((transaction) => ({
        hash: transaction.hash,
        block_number: transaction.block_number,
        from_address: transaction.from_address,
        to_address: transaction.to_address ?? null,
        created_at: transaction.created_at,
      })),
    ),
  ) as Transaction[]
}

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 [watchlist, setWatchlist] = useState<string[]>([])
  const activityContext = useMemo(
    () =>
      summarizeChainActivity({
        blocks: initialLatestBlocks.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: initialLatestBlocks[0]?.number ?? null,
        latestBlockTimestamp: initialLatestBlocks[0]?.timestamp ?? null,
        freshness: resolveEffectiveFreshness(initialStats, initialBridgeStatus),
        diagnostics: initialStats?.diagnostics ?? initialBridgeStatus?.data?.diagnostics ?? null,
      }),
    [chainId, initialBridgeStatus, initialLatestBlocks, initialStats, 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 (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 >= 12) return addresses
      }
    }

    return addresses
  }, [recentTransactions])

  const handleOpenAddress = (event: React.FormEvent) => {
    event.preventDefault()
    const normalized = normalizeAddress(query)
    if (!normalized) return
    router.push(`/addresses/${normalized}`)
  }

  return (
    <div className="container mx-auto px-4 py-6 sm:py-8">
      <PageIntro
        eyebrow="Address Discovery"
        title="Addresses"
        description="Open any Chain 138 address directly, revisit saved watchlist entries, or branch into recent activity discovered from indexed transactions."
        actions={[
          { href: '/watchlist', label: 'Open watchlist' },
          { href: '/transactions', label: 'Recent transactions' },
          { href: '/search', label: 'Search explorer' },
        ]}
      />

      <div className="mb-6">
        <ActivityContextPanel context={activityContext} title="Recent Address Activity Context" />
        <FreshnessTrustNote
          className="mt-3"
          context={activityContext}
          stats={initialStats}
          bridgeStatus={initialBridgeStatus}
          scopeLabel="Recently active addresses are derived from the latest visible indexed transactions."
        />
      </div>

      <Card className="mb-6" title="Open An Address">
        <form onSubmit={handleOpenAddress} className="flex flex-col gap-3 md:flex-row">
          <input
            type="text"
            value={query}
            onChange={(event) => setQuery(event.target.value)}
            placeholder="0x..."
            className="flex-1 rounded-lg border border-gray-300 px-4 py-2 focus:outline-none focus:ring-2 focus:ring-primary-500"
          />
          <button
            type="submit"
            disabled={!normalizeAddress(query)}
            className="rounded-lg bg-primary-600 px-6 py-2 text-white hover:bg-primary-700 disabled:cursor-not-allowed disabled:opacity-50"
          >
            Open address
          </button>
        </form>
        <p className="mt-3 text-sm text-gray-600 dark:text-gray-400">
          Open any Chain 138 address directly, or jump into your saved watchlist below.
        </p>
      </Card>

      <div className="grid gap-6 lg:grid-cols-2">
        <Card title="Saved Watchlist">
          {watchlist.length === 0 ? (
            <p className="text-sm text-gray-600 dark:text-gray-400">
              No saved addresses yet. Address detail pages let you add entries to the shared explorer watchlist.
            </p>
          ) : (
            <div className="space-y-3">
              {watchlist.map((entry) => (
                <Link key={entry} href={`/addresses/${entry}`} className="block text-primary-600 hover:underline">
                  <Address address={entry} showCopy={false} />
                </Link>
              ))}
              <div className="pt-2">
                <Link href="/watchlist" className="text-sm text-primary-600 hover:underline">
                  Open the full watchlist →
                </Link>
              </div>
            </div>
          )}
        </Card>

        <Card title="Recently Active Addresses">
          {activeAddresses.length === 0 ? (
            <p className="text-sm text-gray-600 dark:text-gray-400">
              Recent address activity is unavailable in the latest visible transaction sample. You can still open an address directly above.
            </p>
          ) : (
            <div className="space-y-3">
              {activeAddresses.map((entry) => (
                <Link key={entry} href={`/addresses/${entry}`} className="block text-primary-600 hover:underline">
                  <Address address={entry} showCopy={false} />
                </Link>
              ))}
            </div>
          )}
        </Card>
      </div>
    </div>
  )
}

export const getServerSideProps: GetServerSideProps<AddressesPageProps> = async () => {
  const chainId = Number(process.env.NEXT_PUBLIC_CHAIN_ID || '138')
  const [transactionsResult, blocksResult, statsResult, bridgeResult] = await Promise.all([
    fetchPublicJson<{ items?: unknown[] }>('/api/v2/transactions?page=1&page_size=20').catch(() => null),
    fetchPublicJson<{ items?: Array<{ height?: number | string | null; timestamp?: string | null }> }>('/api/v2/blocks?page=1&page_size=3').catch(() => null),
    fetchPublicJson<Record<string, unknown>>('/api/v2/stats').catch(() => null),
    fetchPublicJson<MissionControlBridgeStatusResponse>('/explorer-api/v1/track1/bridge/status').catch(() => null),
  ])
  const initialRecentTransactions = Array.isArray(transactionsResult?.items)
    ? transactionsResult.items.map((item) => normalizeTransaction(item as never, chainId))
    : []
  const initialLatestBlocks = Array.isArray(blocksResult?.items)
    ? blocksResult.items
        .map((item) => ({
          number: Number(item.height || 0),
          timestamp: item.timestamp || '',
        }))
        .filter((item) => Number.isFinite(item.number) && item.number > 0 && item.timestamp)
    : []

  return {
    props: {
      initialRecentTransactions: serializeRecentTransactions(initialRecentTransactions),
      initialLatestBlocks,
      initialStats: statsResult ? normalizeExplorerStats(statsResult as never) : null,
      initialBridgeStatus: bridgeResult,
    },
  }
}
