'use client'

import Link from 'next/link'
import { useEffect, useMemo, useState } from 'react'
import { Card, Address } from '@/libs/frontend-ui-primitives'
import PageIntro from '@/components/common/PageIntro'
import { Explain, useUiMode } from '@/components/common/UiModeContext'
import { accessApi, type WalletAccessSession } from '@/services/api/access'
import { addressesApi, type AddressInfo, type TransactionSummary } from '@/services/api/addresses'
import {
  isWatchlistEntry,
  normalizeWatchlistAddress,
  readWatchlistFromStorage,
  sanitizeWatchlistEntries,
  toggleWatchlistEntry,
  writeWatchlistToStorage,
} from '@/utils/watchlist'

type TrackedAddressSnapshot = {
  address: string
  info: AddressInfo | null
  recentTransaction: TransactionSummary | null
}

function shortAddress(value?: string | null): string {
  if (!value) return 'Unknown'
  if (value.length <= 14) return value
  return `${value.slice(0, 6)}...${value.slice(-4)}`
}

export default function WatchlistPage() {
  const { mode } = useUiMode()
  const [entries, setEntries] = useState<string[]>([])
  const [walletSession, setWalletSession] = useState<WalletAccessSession | null>(null)
  const [snapshots, setSnapshots] = useState<Record<string, TrackedAddressSnapshot>>({})
  const [loadingSnapshots, setLoadingSnapshots] = useState(false)

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

    const syncSession = () => setWalletSession(accessApi.getStoredWalletSession())
    const syncWatchlist = () => {
      try {
        setEntries(readWatchlistFromStorage(window.localStorage))
      } catch {
        setEntries([])
      }
    }

    syncSession()
    syncWatchlist()
    window.addEventListener('explorer-access-session-changed', syncSession)
    window.addEventListener('storage', syncWatchlist)
    return () => {
      window.removeEventListener('explorer-access-session-changed', syncSession)
      window.removeEventListener('storage', syncWatchlist)
    }
  }, [])

  useEffect(() => {
    let cancelled = false

    if (entries.length === 0) {
      setSnapshots({})
      setLoadingSnapshots(false)
      return () => {
        cancelled = true
      }
    }

    setLoadingSnapshots(true)
    Promise.all(
      entries.map(async (address) => {
        const [infoResponse, transactionsResponse] = await Promise.all([
          addressesApi.getSafe(138, address),
          addressesApi.getTransactionsSafe(138, address, 1, 1),
        ])

        return {
          address,
          info: infoResponse.ok ? infoResponse.data : null,
          recentTransaction: transactionsResponse.ok ? transactionsResponse.data[0] ?? null : null,
        } satisfies TrackedAddressSnapshot
      }),
    )
      .then((results) => {
        if (cancelled) return
        const next: Record<string, TrackedAddressSnapshot> = {}
        for (const result of results) {
          next[result.address.toLowerCase()] = result
        }
        setSnapshots(next)
      })
      .catch(() => {
        if (cancelled) return
        setSnapshots({})
      })
      .finally(() => {
        if (cancelled) return
        setLoadingSnapshots(false)
      })

    return () => {
      cancelled = true
    }
  }, [entries])

  const connectedWalletEntry = useMemo(
    () => normalizeWatchlistAddress(walletSession?.address || ''),
    [walletSession?.address],
  )
  const connectedWalletTracked = connectedWalletEntry
    ? isWatchlistEntry(entries, connectedWalletEntry)
    : false

  const trackedSummaries = useMemo(() => {
    const values = entries
      .map((entry) => snapshots[entry.toLowerCase()])
      .filter((value): value is TrackedAddressSnapshot => Boolean(value))

    return {
      contracts: values.filter((value) => value.info?.is_contract).length,
      eoas: values.filter((value) => value.info && !value.info.is_contract).length,
      withRecentTransactions: values.filter((value) => value.recentTransaction).length,
      totalTransactions: values.reduce(
        (sum, value) => sum + (value.info?.transaction_count || 0),
        0,
      ),
    }
  }, [entries, snapshots])

  const removeEntry = (address: string) => {
    setEntries((current) => {
      const next = current.filter((entry) => entry.toLowerCase() !== address.toLowerCase())
      try {
        writeWatchlistToStorage(window.localStorage, next)
      } catch {}
      return next
    })
  }

  const exportWatchlist = () => {
    if (entries.length === 0) return

    try {
      const blob = new Blob([JSON.stringify(entries, null, 2)], { type: 'application/json' })
      const url = URL.createObjectURL(blob)
      const anchor = document.createElement('a')
      anchor.href = url
      anchor.download = 'explorer-watchlist.json'
      anchor.click()
      URL.revokeObjectURL(url)
    } catch {}
  }

  const importWatchlist = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0]
    if (!file) return

    file.text()
      .then((text) => {
        try {
          const next = sanitizeWatchlistEntries(JSON.parse(text))
          setEntries(next)
          writeWatchlistToStorage(window.localStorage, next)
        } catch {}
      })
      .catch(() => {})

    event.target.value = ''
  }

  const toggleConnectedWallet = () => {
    if (!connectedWalletEntry || typeof window === 'undefined') return
    const next = toggleWatchlistEntry(entries, connectedWalletEntry)
    writeWatchlistToStorage(window.localStorage, next)
    setEntries(next)
  }

  return (
    <div className="container mx-auto px-4 py-6 sm:py-8">
      <PageIntro
        eyebrow="Tracked Entities"
        title="Watchlist"
        description={
          mode === 'guided'
            ? 'Track the addresses that matter most, review a quick explorer snapshot for each one, and move directly into address detail or recent indexed transactions from one shared workflow surface.'
            : 'Track important addresses, review quick snapshots, and jump directly into explorer workflows.'
        }
        actions={[
          { href: '/addresses', label: 'Browse addresses' },
          { href: '/search', label: 'Search explorer' },
          { href: '/transactions', label: 'Recent transactions' },
        ]}
      />

      <Card title="Tracked Entities Overview">
        <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
          <div className="rounded-xl border border-gray-200 p-4 dark:border-gray-700">
            <div className="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Tracked addresses</div>
            <div className="mt-1 text-2xl font-semibold text-gray-900 dark:text-white">{entries.length}</div>
          </div>
          <div className="rounded-xl border border-gray-200 p-4 dark:border-gray-700">
            <div className="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Recent indexed activity</div>
            <div className="mt-1 text-2xl font-semibold text-gray-900 dark:text-white">{trackedSummaries.withRecentTransactions}</div>
            <div className="mt-1 text-sm text-gray-600 dark:text-gray-400">Entries with at least one visible recent transaction.</div>
          </div>
          <div className="rounded-xl border border-gray-200 p-4 dark:border-gray-700">
            <div className="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">EOAs / contracts</div>
            <div className="mt-1 text-2xl font-semibold text-gray-900 dark:text-white">
              {trackedSummaries.eoas} / {trackedSummaries.contracts}
            </div>
          </div>
          <div className="rounded-xl border border-gray-200 p-4 dark:border-gray-700">
            <div className="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Visible tx volume</div>
            <div className="mt-1 text-2xl font-semibold text-gray-900 dark:text-white">
              {trackedSummaries.totalTransactions.toLocaleString()}
            </div>
            <div className="mt-1 text-sm text-gray-600 dark:text-gray-400">Aggregate indexed transaction count across tracked entries.</div>
          </div>
        </div>
        <Explain>
          This view keeps tracked-address shortcuts and quick explorer evidence in one place so Guided mode can explain what each entity represents while Expert mode stays denser.
        </Explain>
      </Card>

      <Card title="Connected Wallet">
        {walletSession ? (
          <div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
            <div>
              <div className="text-sm font-semibold text-gray-900 dark:text-white">
                {shortAddress(walletSession.address)}
              </div>
              <div className="mt-1 break-all text-sm text-gray-600 dark:text-gray-400">
                {walletSession.address}
              </div>
              <div className="mt-2 text-sm text-gray-600 dark:text-gray-400">
                {connectedWalletTracked
                  ? 'This connected wallet is already part of your tracked entity set.'
                  : 'Add this connected wallet into the tracked entity set for faster monitoring and navigation.'}
              </div>
            </div>
            <div className="flex flex-wrap gap-2">
              <button
                type="button"
                onClick={toggleConnectedWallet}
                className="rounded-lg bg-primary-600 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-700"
              >
                {connectedWalletTracked ? 'Remove from watchlist' : 'Track connected wallet'}
              </button>
              <Link
                href={`/addresses/${walletSession.address}`}
                className="rounded-lg border border-gray-300 px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-700 dark:text-gray-200 dark:hover:bg-gray-900/60"
              >
                Open address
              </Link>
            </div>
          </div>
        ) : (
          <div className="text-sm text-gray-600 dark:text-gray-400">
            Connect a wallet from the <Link href="/wallet" className="text-primary-600 hover:underline">wallet tools page</Link> to pin your own address into tracked workflows.
          </div>
        )}
      </Card>

      <Card title="Saved Addresses">
        <div className="mb-4 flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
          <p className="text-sm text-gray-600 dark:text-gray-400">
            {entries.length === 0
              ? 'No saved entries yet.'
              : `${entries.length} saved ${entries.length === 1 ? 'address' : 'addresses'}.`}
          </p>
          <div className="flex flex-wrap gap-2">
            <label className="cursor-pointer rounded-lg bg-gray-100 px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700">
              Import JSON
              <input type="file" accept="application/json" className="hidden" onChange={importWatchlist} />
            </label>
            <button
              type="button"
              onClick={exportWatchlist}
              disabled={entries.length === 0}
              className="rounded-lg bg-primary-600 px-3 py-1.5 text-sm text-white hover:bg-primary-700 disabled:cursor-not-allowed disabled:bg-gray-300 disabled:text-gray-500 disabled:opacity-100 dark:disabled:bg-gray-700 dark:disabled:text-gray-400"
            >
              Export JSON
            </button>
          </div>
        </div>
        {entries.length === 0 ? (
          <div className="space-y-3 text-sm text-gray-600 dark:text-gray-400">
            <p>Your watchlist is empty. Add an address from its detail page to keep it here.</p>
            <div className="flex flex-wrap gap-3">
              <Link href="/addresses" className="text-primary-600 hover:underline">
                Browse addresses →
              </Link>
              <Link href="/search" className="text-primary-600 hover:underline">
                Search the explorer →
              </Link>
            </div>
          </div>
        ) : (
          <div className="space-y-3">
            {entries.map((entry) => {
              const snapshot = snapshots[entry.toLowerCase()]
              const info = snapshot?.info || null
              const recentTransaction = snapshot?.recentTransaction || null

              return (
                <div
                  key={entry}
                  className="rounded-lg border border-gray-200 p-4 dark:border-gray-700"
                >
                  <div className="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
                    <div className="min-w-0">
                      <Link href={`/addresses/${entry}`} className="text-primary-600 hover:underline">
                        <Address address={entry} showCopy={false} />
                      </Link>
                      <div className="mt-2 grid gap-3 sm:grid-cols-2 xl:grid-cols-4">
                        <div>
                          <div className="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Type</div>
                          <div className="mt-1 text-sm text-gray-900 dark:text-white">
                            {info ? (info.is_contract ? 'Contract' : 'EOA') : loadingSnapshots ? 'Loading…' : 'Unknown'}
                          </div>
                        </div>
                        <div>
                          <div className="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Indexed txs</div>
                          <div className="mt-1 text-sm text-gray-900 dark:text-white">
                            {info ? info.transaction_count.toLocaleString() : loadingSnapshots ? 'Loading…' : 'Unknown'}
                          </div>
                        </div>
                        <div>
                          <div className="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Token holdings</div>
                          <div className="mt-1 text-sm text-gray-900 dark:text-white">
                            {info ? info.token_count.toLocaleString() : loadingSnapshots ? 'Loading…' : 'Unknown'}
                          </div>
                        </div>
                        <div>
                          <div className="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Recent visible tx</div>
                          <div className="mt-1 text-sm text-gray-900 dark:text-white">
                            {recentTransaction ? `#${recentTransaction.block_number.toLocaleString()}` : loadingSnapshots ? 'Loading…' : 'None visible'}
                          </div>
                        </div>
                      </div>
                    </div>

                    <div className="flex flex-wrap gap-2">
                      <Link
                        href={`/addresses/${entry}`}
                        className="rounded-lg border border-gray-300 px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-50 dark:border-gray-700 dark:text-gray-200 dark:hover:bg-gray-900/60"
                      >
                        Open address
                      </Link>
                      {recentTransaction ? (
                        <Link
                          href={`/transactions/${recentTransaction.hash}`}
                          className="rounded-lg border border-gray-300 px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-50 dark:border-gray-700 dark:text-gray-200 dark:hover:bg-gray-900/60"
                        >
                          Latest tx
                        </Link>
                      ) : null}
                      <button
                        type="button"
                        onClick={() => removeEntry(entry)}
                        className="rounded-lg bg-gray-100 px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-200 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
                      >
                        Remove
                      </button>
                    </div>
                  </div>
                </div>
              )
            })}
          </div>
        )}
      </Card>
    </div>
  )
}
