import type { GetServerSideProps } from 'next'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { Card, Table, Address } from '@/libs/frontend-ui-primitives'
import Link from 'next/link'
import { transactionsApi, Transaction } from '@/services/api/transactions'
import { formatWeiAsEth } from '@/utils/format'
import EntityBadge from '@/components/common/EntityBadge'
import PageIntro from '@/components/common/PageIntro'
import { fetchPublicJson } from '@/utils/publicExplorer'
import { normalizeTransaction } from '@/services/api/blockscout'

interface TransactionsPageProps {
  initialTransactions: Transaction[]
}

function serializeTransactionList(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,
        token_transfers: Array.isArray(transaction.token_transfers)
          ? transaction.token_transfers.map((transfer) => ({ token_address: transfer.token_address }))
          : [],
      })),
    ),
  ) as Transaction[]
}

export default function TransactionsPage({ initialTransactions }: TransactionsPageProps) {
  const pageSize = 20
  const [transactions, setTransactions] = useState<Transaction[]>(initialTransactions)
  const [loading, setLoading] = useState(initialTransactions.length === 0)
  const [page, setPage] = useState(1)
  const chainId = parseInt(process.env.NEXT_PUBLIC_CHAIN_ID || '138')

  const loadTransactions = useCallback(async () => {
    setLoading(true)
    try {
      const { ok, data } = await transactionsApi.listSafe(chainId, page, pageSize)
      setTransactions(ok ? data : [])
    } catch (error) {
      console.error('Failed to load transactions:', error)
      setTransactions([])
    } finally {
      setLoading(false)
    }
  }, [chainId, page, pageSize])

  useEffect(() => {
    if (page === 1 && initialTransactions.length > 0) {
      setTransactions(initialTransactions)
      setLoading(false)
      return
    }
    void loadTransactions()
  }, [initialTransactions, loadTransactions, page])

  const transactionSummary = useMemo(() => {
    const sampleSize = transactions.length
    if (sampleSize === 0) {
      return {
        sampleSize: 0,
        successRate: 0,
        contractCreations: 0,
        tokenTransferTransactions: 0,
        averageFee: null as string | null,
      }
    }

    const successes = transactions.filter((transaction) => transaction.status === 1).length
    const contractCreations = transactions.filter((transaction) => Boolean(transaction.contract_address)).length
    const tokenTransferTransactions = transactions.filter(
      (transaction) => (transaction.token_transfers?.length || 0) > 0,
    ).length
    const feeValues = transactions
      .map((transaction) => {
        if (!transaction.fee) return null
        const numeric = Number(transaction.fee)
        return Number.isFinite(numeric) ? numeric : null
      })
      .filter((value): value is number => value != null)
    const averageFee =
      feeValues.length > 0
        ? formatWeiAsEth(Math.round(feeValues.reduce((sum, value) => sum + value, 0) / feeValues.length).toString(), 6)
        : null

    return {
      sampleSize,
      successRate: Math.round((successes / sampleSize) * 100),
      contractCreations,
      tokenTransferTransactions,
      averageFee,
    }
  }, [transactions])

  const showPagination = page > 1 || transactions.length > 0
  const canGoNext = transactions.length === pageSize

  const columns = [
    {
      header: 'Hash',
      accessor: (tx: Transaction) => (
        <Link href={`/transactions/${tx.hash}`} className="text-primary-600 hover:underline">
          <Address address={tx.hash} truncate showCopy={false} />
        </Link>
      ),
    },
    {
      header: 'Block',
      accessor: (tx: Transaction) => (
        <Link href={`/blocks/${tx.block_number}`} className="text-primary-600 hover:underline">
          {tx.block_number}
        </Link>
      ),
    },
    {
      header: 'From',
      accessor: (tx: Transaction) => (
        <Link href={`/addresses/${tx.from_address}`} className="text-primary-600 hover:underline">
          <Address address={tx.from_address} truncate showCopy={false} />
        </Link>
      ),
    },
    {
      header: 'To',
      accessor: (tx: Transaction) => tx.to_address ? (
        <Link href={`/addresses/${tx.to_address}`} className="text-primary-600 hover:underline">
          <Address address={tx.to_address} truncate showCopy={false} />
        </Link>
      ) : <span className="text-gray-400">Contract Creation</span>,
    },
    {
      header: 'Value',
      accessor: (tx: Transaction) => formatWeiAsEth(tx.value),
    },
    {
      header: 'Status',
      accessor: (tx: Transaction) => (
        <span className={tx.status === 1 ? 'text-green-600' : 'text-red-600'}>
          {tx.status === 1 ? 'Success' : 'Failed'}
        </span>
      ),
    },
  ]

  return (
    <div className="container mx-auto px-4 py-6 sm:py-8">
      <PageIntro
        eyebrow="Indexed Flow"
        title="Transactions"
        description="Review recent Chain 138 transactions and move directly into the linked block, address, search, and watchlist surfaces from here."
        actions={[
          { href: '/blocks', label: 'Open blocks' },
          { href: '/addresses', label: 'Browse addresses' },
          { href: '/watchlist', label: 'Open watchlist' },
        ]}
      />

      {!loading && transactions.length > 0 && (
        <div className="mb-6 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
          <Card>
            <div className="text-sm font-semibold uppercase tracking-wide text-gray-600 dark:text-gray-400">Sample Size</div>
            <div className="mt-2 text-2xl font-bold text-gray-900 dark:text-white">{transactionSummary.sampleSize.toLocaleString()}</div>
            <div className="mt-2 text-sm text-gray-600 dark:text-gray-400">Transactions on the current explorer page.</div>
          </Card>
          <Card>
            <div className="text-sm font-semibold uppercase tracking-wide text-gray-600 dark:text-gray-400">Success Rate</div>
            <div className="mt-2 flex items-center gap-2">
              <span className="text-2xl font-bold text-gray-900 dark:text-white">{transactionSummary.successRate}%</span>
              <EntityBadge label={transactionSummary.successRate >= 90 ? 'healthy' : 'mixed'} tone={transactionSummary.successRate >= 90 ? 'success' : 'warning'} />
            </div>
            <div className="mt-2 text-sm text-gray-600 dark:text-gray-400">Based on the visible recent transaction sample.</div>
          </Card>
          <Card>
            <div className="text-sm font-semibold uppercase tracking-wide text-gray-600 dark:text-gray-400">Contract Creations</div>
            <div className="mt-2 text-2xl font-bold text-gray-900 dark:text-white">{transactionSummary.contractCreations.toLocaleString()}</div>
            <div className="mt-2 text-sm text-gray-600 dark:text-gray-400">New contracts created in the visible sample.</div>
          </Card>
          <Card>
            <div className="text-sm font-semibold uppercase tracking-wide text-gray-600 dark:text-gray-400">Avg Sample Fee</div>
            <div className="mt-2 text-2xl font-bold text-gray-900 dark:text-white">{transactionSummary.averageFee || 'Unavailable'}</div>
            <div className="mt-2 text-sm text-gray-600 dark:text-gray-400">
              Token-transfer txs: {transactionSummary.tokenTransferTransactions.toLocaleString()}
            </div>
          </Card>
        </div>
      )}

      {loading ? (
        <Card>
          <p className="text-sm text-gray-600 dark:text-gray-400">Loading transactions...</p>
        </Card>
      ) : (
        <Table
          columns={columns}
          data={transactions}
          emptyMessage="Recent transactions are unavailable right now."
          keyExtractor={(tx) => tx.hash}
        />
      )}

      {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="Next Steps">
          <p className="text-sm leading-6 text-gray-600 dark:text-gray-400">
            Use the linked hashes above to inspect detail pages, or pivot into block production, address activity, and explorer-wide search.
          </p>
          <div className="mt-4 flex flex-wrap gap-3 text-sm">
            <Link href="/blocks" className="text-primary-600 hover:underline">
              Blocks →
            </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<TransactionsPageProps> = async () => {
  const chainId = Number(process.env.NEXT_PUBLIC_CHAIN_ID || '138')
  const transactionsResult = await fetchPublicJson<{ items?: unknown[] }>('/api/v2/transactions?page=1&page_size=20').catch(() => null)
  const initialTransactions = Array.isArray(transactionsResult?.items)
    ? transactionsResult.items.map((item) => normalizeTransaction(item as never, chainId))
    : []

  return {
    props: {
      initialTransactions: serializeTransactionList(initialTransactions),
    },
  }
}
