'use client'

import { useState, useEffect, useRef } from 'react'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
import { useLocale } from 'next-intl'
import { useAccount, useSignMessage } from 'wagmi'
import type { BotTrade } from '@/types'
import { getTrades, getUserPublic } from '@/lib/api'
import { useDashboardStore } from '@/store/dashboard'
import { getCachedViewEnvelope, getOrCreateViewEnvelope, type SignedEnvelope } from '@/lib/signedRequest'
import TradeTable from '@/components/trades/TradeTable'
import OpenPositions from '@/components/positions/OpenPositions'
import PageHint from '@/components/ui/PageHint'

export default function TradesPageClient() {
  const intlLocale = useLocale()
  const isZh = false  // i18n shelved — Chinese branches kept as dead code for future revival; see messages/zh.json
  const { address, isConnected } = useAccount()
  const { signMessageAsync } = useSignMessage()
  const { isSubscribed, hlApiKeySet, paperMode,
          setSubscribed, setHlApiKeySet, setPaperMode, setBotReadiness } = useDashboardStore()
  const pathname = usePathname()
  const locale = pathname.split('/')[1] || 'en'

  const [mounted, setMounted] = useState(false)
  const [trades, setTrades] = useState<BotTrade[]>([])
  const [loading, setLoading] = useState(true)
  const [loadErr, setLoadErr] = useState('')
  const [needsUnlock, setNeedsUnlock] = useState(false)
  const [unlocking, setUnlocking] = useState(false)

  const aliveRef = useRef(true)
  useEffect(() => {
    setMounted(true)
    aliveRef.current = true
    return () => { aliveRef.current = false }
  }, [])

  // genRef guards loadAll against stale-closure wallet-switch races.
  // `snapAddr !== address` inside an async function compares two copies of
  // the same closure-captured value — it's always equal even when the wallet
  // has changed, so the check is a no-op. genRef is a mutable ref that every
  // closure can read, so `gen !== genRef.current` correctly detects staleness.
  const genRef = useRef(0)
  useEffect(() => { genRef.current++ }, [address])

  // B41: TradesPageClient can be the entry point (direct navigation to /trades)
  // without DashboardClient or BotConfigPanel ever running. In that case the
  // Zustand store has isSubscribed=false (initial default), causing the
  // "Bot not configured" banner to appear for valid subscribers.
  // Fix: fetch /user/{wallet}/public here too — it's lightweight, unauthenticated,
  // and idempotent with the same fetch DashboardClient does.
  useEffect(() => {
    if (!address || !isConnected) return
    let cancelled = false
    const snap = address
    getUserPublic(snap.toLowerCase())
      .then(u => {
        if (cancelled || snap !== address) return
        setSubscribed(u.active)
        setHlApiKeySet(u.hl_api_key_set)
        setBotReadiness(u.hl_api_key_set ? 'saved' : 'unknown')
        setPaperMode(!!u.paper_mode)
      })
      .catch(() => {})
    return () => { cancelled = true }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [address, isConnected])

  // Load public posts always; load private trades only if we have a view
  // envelope. `forcedEnv` lets the in-page Unlock button pass a freshly-minted
  // one so the user never has to detour through the Settings page first.
  async function loadAll(forcedEnv?: SignedEnvelope) {
    if (!address || !isConnected) {
      setTrades([]); setLoading(false); setLoadErr(''); setNeedsUnlock(false)
      return
    }
    const gen = genRef.current
    const snapAddr = address   // for API calls only — NOT for stale detection
    setLoading(true)
    const env = forcedEnv
      ?? getCachedViewEnvelope('view_trades', snapAddr)
      ?? getCachedViewEnvelope('view_user', snapAddr)
    let failed = false
    try {
      const t = env
        ? await getTrades(snapAddr, env, 500, 1).catch(e => {
          failed = true
          setLoadErr(e instanceof Error ? e.message : 'Failed to load trades')
          return [] as BotTrade[]
        })
        : []
      // Use genRef — NOT `snapAddr !== address` (stale closure: both are the
      // same closed-over value and the comparison is always false).
      if (!aliveRef.current || gen !== genRef.current) return
      setTrades(t)
      setNeedsUnlock(!env)
      if (env && !failed) setLoadErr('')
    } finally {
      if (aliveRef.current && gen === genRef.current) setLoading(false)
    }
  }

  useEffect(() => {
    // B27/B35: clear stale previous-wallet data BEFORE the async fetch so the
    // UI never briefly shows another wallet's private trades.
    setTrades([])
    setNeedsUnlock(false)
    setLoadErr('')
    // On navigation we only use a cached envelope — never auto-popup the
    // wallet. If none is cached the user unlocks explicitly via the button.
    void loadAll()
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [address, isConnected])

  // Mint a view envelope right here (one signature) and reload — no Settings detour.
  async function handleUnlock() {
    if (!address) return
    setUnlocking(true)
    setLoadErr('')
    try {
      // view_user is a superset accepted by /trades, /positions/open,
      // /positions/today — one signature unlocks everything on this page.
      // Previously view_trades was used here, but that left OpenPositions
      // locked (it requires view_positions or view_user).
      const env = await getOrCreateViewEnvelope({
        action: 'view_user', wallet: address, signMessageAsync,
      })
      await loadAll(env)
    } catch (e) {
      // User rejected the signature or it failed — keep the Unlock CTA visible.
      const msg = e instanceof Error ? e.message : 'Signature cancelled'
      if (aliveRef.current) setLoadErr(/reject|denied|cancel/i.test(msg) ? '' : msg)
    } finally {
      if (aliveRef.current) setUnlocking(false)
    }
  }

  // B40: paper users have no HL key but the bot IS configured for them — don't
  //      show "Bot not configured" just because hlApiKeySet is false.
  // B41: on cold start (navigating directly to /trades), isSubscribed starts
  //      false in the store until DashboardClient or BotConfigPanel fetches
  //      /user/public. Guard with !loading so the banner only appears once
  //      the page has confirmed the wallet is genuinely unconfigured.
  const needsSetup = mounted && isConnected && !loading &&
    (!isSubscribed || (!hlApiKeySet && !paperMode))

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <h1 className="page-title">{isZh ? '交易执行' : 'Trades'}</h1>
          {/* Says what the page is, not where things sit — the section cards
              below are self-labelled ("Open positions", KPI row, table). */}
          <PageHint>
            What the bot holds right now, and every trade it has closed.
          </PageHint>
        </div>
      </div>

      {/* Guest view: a zero-filled KPI row + empty table reads like a broken
          dashboard. Show one connect prompt instead and skip the data UI. */}
      {mounted && !isConnected ? (
        <div className="card" style={{ padding: '32px 28px', textAlign: 'center' }}>
          <div style={{ fontSize: 15, fontWeight: 600, marginBottom: 6 }}>Connect your wallet to see your trades</div>
          <div style={{ fontSize: 13, color: 'var(--ink-3)', lineHeight: 1.6 }}>
            Positions and trade history are wallet-bound and private.
            Use the Connect wallet button in the top-right corner.
          </div>
        </div>
      ) : (
      <>
      {needsSetup && (
        <div className="card" style={{
          padding: '14px 18px', marginBottom: 16,
          background: 'var(--amber-soft)',
          borderColor: 'color-mix(in oklab, var(--amber) 22%, var(--line))',
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          flexWrap: 'wrap', gap: 12,
        }}>
          <div>
            <div style={{ fontSize: 13, fontWeight: 600 }}>{isZh ? '机器人尚未配置完成' : 'Bot not configured'}</div>
            <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 2 }}>
              {isZh ? '在机器人开始交易前，请先去设置页订阅并绑定 Hyperliquid API。' : 'Subscribe and link your Hyperliquid API wallet on the Settings page before the bot can trade.'}
            </div>
          </div>
          <Link
            href={`/${locale}/settings`}
            className="btn amber"
            style={{ padding: '8px 16px', fontSize: 13, textDecoration: 'none' }}
          >
            {isZh ? '前往设置 →' : 'Go to Settings →'}
          </Link>
        </div>
      )}

      <OpenPositions />

      {mounted && isConnected && !loading && needsUnlock && (
        <div className="card" style={{
          padding: 16, margin: '12px 0', textAlign: 'center', fontSize: 13,
          background: 'var(--amber-soft)',
          borderColor: 'color-mix(in oklab, var(--amber) 22%, var(--line))',
        }}>
          <div style={{ marginBottom: 10, color: 'var(--ink-2)' }}>
            🔒 Your trade history is private. Sign once to unlock it on this device
            (valid for a few minutes, no transaction, no gas).
          </div>
          <button className="btn amber" style={{ fontSize: 13, padding: '8px 16px' }}
            disabled={unlocking} onClick={handleUnlock}>
            {unlocking ? 'Waiting for signature…' : 'Unlock trade history'}
          </button>
        </div>
      )}

      {!loading && loadErr && (
        <div className="card" style={{ padding: 16, margin: '12px 0', textAlign: 'center',
                                       color: 'var(--down)', fontSize: 13 }}>
          ⚠️ {isZh ? `无法加载交易历史：${loadErr}` : `Couldn’t load trade history — ${loadErr}`}
          <button className="btn ghost" style={{ fontSize: 12, padding: '5px 12px', marginLeft: 10 }}
            onClick={() => location.reload()}>{isZh ? '重试' : 'Retry'}</button>
        </div>
      )}

      <TradeTable trades={trades} loading={loading} locked={needsUnlock} />
      </>
      )}
    </div>
  )
}
