import type { GetServerSideProps } from 'next'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { blocksApi, Block } from '@/services/api/blocks'
import { Card, Address } from '@/libs/frontend-ui-primitives'
import Link from 'next/link'
import PageIntro from '@/components/common/PageIntro'
import { formatTimestamp } from '@/utils/format'
import { fetchPublicJson } from '@/utils/publicExplorer'
import { normalizeBlock, normalizeTransaction } from '@/services/api/blockscout'
import type { Transaction } from '@/services/api/transactions'
import { transactionsApi } from '@/services/api/transactions'
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, shouldExplainEmptyHeadBlocks } from '@/utils/explorerFreshness'

interface BlocksPageProps {
  initialBlocks: Block[]
  initialRecentTransactions: Transaction[]
  initialStats: ExplorerStats | null
  initialBridgeStatus: MissionControlBridgeStatusResponse | null
}

function serializeTransactions(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,
        value: transaction.value,
        status: transaction.status ?? null,
        contract_address: transaction.contract_address ?? null,
        fee: transaction.fee ?? null,
        created_at: transaction.created_at,
      })),
    ),
  ) as Transaction[]
}

export default function BlocksPage({
  initialBlocks,
  initialRecentTransactions,
  initialStats,
  initialBridgeStatus,
}: BlocksPageProps) {
  const pageSize = 20
  const [blocks, setBlocks] = useState<Block[]>(initialBlocks)
  const [recentTransactions, setRecentTransactions] = useState<Transaction[]>(initialRecentTransactions)
  const [loading, setLoading] = useState(initialBlocks.length === 0)
  const [page, setPage] = useState(1)
  const chainId = parseInt(process.env.NEXT_PUBLIC_CHAIN_ID || '138')

  const loadBlocks = useCallback(async () => {
    setLoading(true)
    try {
      const response = await blocksApi.list({
        chain_id: chainId,
        page,
        page_size: pageSize,
        sort: 'number',
        order: 'desc',
      })
      setBlocks(response.data)
    } catch (error) {
      console.error('Failed to load blocks:', error)
      setBlocks([])
    } finally {
      setLoading(false)
    }
  }, [chainId, page, pageSize])

  useEffect(() => {
    if (page === 1 && initialBlocks.length > 0) {
      setBlocks(initialBlocks)
      setLoading(false)
      return
    }
    void loadBlocks()
  }, [initialBlocks, loadBlocks, page])

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

    let active = true
    transactionsApi.listSafe(chainId, 1, 5)
      .then(({ ok, data }) => {
        if (active && ok && data.length > 0) {
          setRecentTransactions(data)
        }
      })
      .catch(() => {
        if (active) {
          setRecentTransactions([])
        }
      })

    return () => {
      active = false
    }
  }, [chainId, initialRecentTransactions])

  const showPagination = page > 1 || blocks.length > 0
  const canGoNext = blocks.length === pageSize
  const activityContext = useMemo(
    () =>
      summarizeChainActivity({
        blocks,
        transactions: recentTransactions,
        latestBlockNumber: blocks[0]?.number ?? null,
        latestBlockTimestamp: blocks[0]?.timestamp ?? null,
        freshness: resolveEffectiveFreshness(initialStats, initialBridgeStatus),
        diagnostics: initialStats?.diagnostics ?? initialBridgeStatus?.data?.diagnostics ?? null,
      }),
    [blocks, initialBridgeStatus, initialStats, recentTransactions],
  )

  return (
    <div className="container mx-auto px-4 py-6 sm:py-8">
      <PageIntro
        eyebrow="Chain Activity"
        title="Blocks"
        description="Browse recent Chain 138 blocks, then pivot into transactions, addresses, and indexed search without falling into a dead end."
        actions={[
          { href: '/transactions', label: 'Open transactions' },
          { href: '/addresses', label: 'Browse addresses' },
          { href: '/search', label: 'Search explorer' },
        ]}
      />

      <div className="mb-6">
        <ActivityContextPanel context={activityContext} title="Block Production Context" />
        <FreshnessTrustNote
          className="mt-3"
          context={activityContext}
          stats={initialStats}
          bridgeStatus={initialBridgeStatus}
          scopeLabel="This page focuses on recent visible head blocks."
        />
      </div>

      {loading ? (
        <Card>
          <p className="text-sm text-gray-600 dark:text-gray-400">Loading blocks...</p>
        </Card>
      ) : (
        <div className="space-y-4">
          {shouldExplainEmptyHeadBlocks(blocks, activityContext) ? (
            <Card className="border border-amber-200 bg-amber-50/70 dark:border-amber-900/40 dark:bg-amber-950/20">
              <p className="text-sm text-amber-900 dark:text-amber-100">
                Recent head blocks are currently empty; use the latest transaction block for recent visible activity.
              </p>
            </Card>
          ) : null}
          {blocks.length === 0 ? (
            <Card>
              <p className="text-sm text-gray-600 dark:text-gray-400">Recent blocks are unavailable right now.</p>
              <div className="mt-4 flex flex-wrap gap-3 text-sm">
                <Link href="/transactions" className="text-primary-600 hover:underline">
                  Open recent transactions →
                </Link>
                <Link href="/search" className="text-primary-600 hover:underline">
                  Search by block number →
                </Link>
              </div>
            </Card>
          ) : (
            blocks.map((block) => (
              <Card key={block.number}>
                <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                  <div>
                    <Link
                      href={`/blocks/${block.number}`}
                      className="text-lg font-semibold text-primary-600 hover:text-primary-700"
                    >
                      Block #{block.number}
                    </Link>
                    <div className="mt-1 text-sm text-gray-600 dark:text-gray-400">
                      <Address address={block.hash} truncate showCopy={false} />
                    </div>
                    <div className="mt-2 text-sm text-gray-600 dark:text-gray-400">
                      Miner:{' '}
                      <Link href={`/addresses/${block.miner}`} className="text-primary-600 hover:underline">
                        <Address address={block.miner} truncate showCopy={false} />
                      </Link>
                    </div>
                  </div>
                  <div className="text-left sm:text-right">
                    <div className="text-sm">
                      {formatTimestamp(block.timestamp)}
                    </div>
                    <div className="text-sm text-gray-600 dark:text-gray-400">
                      {block.transaction_count} transactions
                    </div>
                  </div>
                </div>
              </Card>
            ))
          )}
        </div>
      )}

      {showPagination && (
        <div className="mt-6 flex flex-wrap items-center justify-center gap-3">
          <button
            onClick={() => setPage((p) => Math.max(1, p - 1))}
            disabled={loading || page === 1}
            className="rounded bg-gray-200 px-4 py-2 disabled:cursor-not-allowed disabled:opacity-50"
          >
            Previous
          </button>
          <span className="px-3 py-2 text-sm sm:px-4">Page {page}</span>
          <button
            onClick={() => setPage((p) => p + 1)}
            disabled={loading || !canGoNext}
            className="rounded bg-gray-200 px-4 py-2 disabled:cursor-not-allowed disabled:opacity-50"
          >
            Next
          </button>
        </div>
      )}

      <div className="mt-8 grid gap-4 lg:grid-cols-2">
        <Card title="Keep Exploring">
          <p className="text-sm leading-6 text-gray-600 dark:text-gray-400">
            Need a different entry point? Open transaction flow, search directly by block number, or jump into recently active addresses.
          </p>
          <div className="mt-4 flex flex-wrap gap-3 text-sm">
            <Link href="/transactions" className="text-primary-600 hover:underline">
              Transactions →
            </Link>
            <Link href="/addresses" className="text-primary-600 hover:underline">
              Addresses →
            </Link>
            <Link href="/search" className="text-primary-600 hover:underline">
              Search →
            </Link>
          </div>
        </Card>
      </div>
    </div>
  )
}

export const getServerSideProps: GetServerSideProps<BlocksPageProps> = async () => {
  const chainId = Number(process.env.NEXT_PUBLIC_CHAIN_ID || '138')
  const [blocksResult, transactionsResult, statsResult, bridgeResult] = await Promise.all([
    fetchPublicJson<{ items?: unknown[] }>('/api/v2/blocks?page=1&page_size=20').catch(() => null),
    fetchPublicJson<{ items?: unknown[] }>('/api/v2/transactions?page=1&page_size=5').catch(() => null),
    fetchPublicJson<Record<string, unknown>>('/api/v2/stats').catch(() => null),
    fetchPublicJson<MissionControlBridgeStatusResponse>('/explorer-api/v1/track1/bridge/status').catch(() => null),
  ])

  return {
    props: {
      initialBlocks: Array.isArray(blocksResult?.items)
        ? blocksResult.items.map((item) => normalizeBlock(item as never, chainId))
        : [],
      initialRecentTransactions: Array.isArray(transactionsResult?.items)
        ? serializeTransactions(transactionsResult.items.map((item) => normalizeTransaction(item as never, chainId)))
        : [],
      initialStats: statsResult ? normalizeExplorerStats(statsResult as never) : null,
      initialBridgeStatus: bridgeResult,
    },
  }
}
