'use client'

import { useState, useEffect, useMemo } from 'react'
import dynamic from 'next/dynamic'
import { useLocale } from 'next-intl'
import type { TrumpPost } from '@/types'
import { getPosts, getFundingSnapshot, type FundingSnapshot } from '@/lib/api'
import { swrFetch } from '@/lib/cache'
import PostRow from '@/components/dashboard/PostCards'
import SystemControl from '@/components/signals/SystemControl'
import InfoTip from '@/components/ui/InfoTip'

// MacroPanel is 631 lines with heavy indicator math — split it out.
const MacroPanel = dynamic(() => import('@/components/btc/MacroPanel'), {
  ssr: false,
  loading: () => <div style={{ height: 280, background: 'var(--bg-sunk)', borderRadius: 12, marginBottom: 20 }} />,
})

/**
 * System 2 — BTC bottom-reversal. Its own dedicated page.
 * Shows the scanner control + ONLY source === 'btc_bottom_reversal' signals.
 */

const SENTIMENTS = ['all', 'bullish', 'bearish', 'neutral'] as const
type SentimentFilter = (typeof SENTIMENTS)[number]
type BtcTab = 'bottom' | 'funding'

interface MacroVibesPageProps {
  initialPosts?: TrumpPost[] | null
  initialFundingSnapshot?: FundingSnapshot | null
}

export default function MacroVibesPage({
  initialPosts = null,
  initialFundingSnapshot = null,
}: MacroVibesPageProps) {
  const locale = useLocale()
  const isZh = false  // i18n shelved — Chinese branches kept as dead code for future revival; see messages/zh.json
  const [posts, setPosts]     = useState<TrumpPost[]>(initialPosts ?? [])
  const [loading, setLoading] = useState(initialPosts === null)
  const [loadErr, setLoadErr] = useState('')
  const [sentFilter, setSentFilter] = useState<SentimentFilter>('all')
  const [tab, setTab] = useState<BtcTab>('bottom')

  // Tab-scoped post source. 'bottom' = MVRV/200WMA confluence,
  // 'funding' = funding-rate extreme reversal.
  const tabSource = tab === 'bottom' ? 'btc_bottom_reversal' : 'funding_reversal'

  useEffect(() => {
    // Fetch BY SOURCE, not the latest-500 global feed. These scanner signals
    // are rare (2–4/cycle, hourly) and were being pushed off the latest-500
    // page by frequent Trump posts — making the Macro page look empty even
    // when signals existed. Server-side source filter guarantees we get them.
    setLoading(true)
    swrFetch(
      `posts-src-${tabSource}`,
      3 * 60_000,
      () => getPosts(200, 1, tabSource),
      fresh => setPosts(fresh),
    )
      .then(p => { setPosts(p); setLoadErr('') })
      .catch(e => setLoadErr(e instanceof Error ? e.message : (isZh ? '信号加载失败' : 'Failed to load signals')))
      .finally(() => setLoading(false))
  }, [tabSource, isZh])

  const btcPosts = useMemo(
    () => posts.filter(p => (p.source || '') === tabSource),
    [posts, tabSource],
  )
  const filtered = useMemo(
    () => btcPosts.filter(p => sentFilter === 'all' || p.sentiment === sentFilter),
    [btcPosts, sentFilter],
  )

  const sentimentLabels: Record<SentimentFilter, string> = {
    all: isZh ? '全部' : 'All',
    bullish: isZh ? '看多' : 'Bullish',
    bearish: isZh ? '看空' : 'Bearish',
    neutral: isZh ? '中性' : 'Neutral',
  }

  return (
    <div className="page">
      <div className="page-head">
        <div>
          {/* No "You open · bot manages" badge — the SystemControl strip right
              below says the same thing verbatim ("You open · bot manages exit"). */}
          <h1 className="page-title" style={{ margin: 0 }}>{isZh ? '宏观氛围' : 'Macro Vibes'}</h1>
        </div>
        <span className="chip"><span className="live-dot" />Live</span>
      </div>

      <SystemControl system="btc" />

      {/* Tabs + inline description on the same row — avoids a separate
          "section hint" block that adds a third layer before the data. */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 16,
                    flexWrap: 'wrap', marginTop: 14, marginBottom: 14 }}>
        <div className="nav-tabs" style={{ background: 'var(--bg-sunk)', flexShrink: 0 }}>
          <button
            onClick={() => setTab('bottom')}
            className={`nav-tab ${tab === 'bottom' ? 'active' : ''}`}
            style={{ border: 'none', cursor: 'pointer' }}
          >
            {isZh ? '周期底部' : 'Macro Bottom'}
          </button>
          <button
            onClick={() => setTab('funding')}
            className={`nav-tab ${tab === 'funding' ? 'active' : ''}`}
            style={{ border: 'none', cursor: 'pointer' }}
          >
            {isZh ? '资金费率反转' : 'Funding Reversal'}
          </button>
        </div>
        <span style={{ fontSize: 12, color: 'var(--ink-3)', lineHeight: 1.4 }}>
          {tab === 'bottom'
            ? <><strong style={{ color: 'var(--ink-2)' }}>≥2 of 3:</strong> AHR999 &lt; 0.45 · 200w MA · Pi Cycle Bottom — long-only, rare.</>
            : <>Fades crowded perps when 30d cumulative funding crosses <strong>±3%</strong> and cools. Hourly.</>}
        </span>
      </div>

      {/* Macro indicator panel — only relevant on the Macro Bottom tab where
          users are reasoning about the broader risk regime. The Funding tab
          has its own live funding panel below. */}
      {tab === 'bottom' && <MacroPanel />}
      {/* SignalMonitor (ETH/LINK Breakout Monitor) unmounted 2026-06-12: the
          backend scanner is disabled (services/funding_signal.py _enabled=False,
          operator-only toggle), so the panel only ever showed "Paused / No
          signals yet" — and breakout scanning is unrelated to funding reversal
          anyway. Component kept at components/dashboard/SignalMonitor.tsx;
          remount here if the scanner is ever re-enabled. */}
      {tab === 'funding' && (
        <FundingPanel
          isZh={isZh}
          initialSnapshot={initialFundingSnapshot}
        />
      )}

      <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', margin: '16px 0 12px' }}>
        {SENTIMENTS.map(f => (
          <button
            key={f}
            onClick={() => setSentFilter(f)}
            style={{
              padding: '4px 10px', borderRadius: 6, border: '1px solid var(--line)',
              background: sentFilter === f ? 'var(--ink)' : 'transparent',
              color: sentFilter === f ? 'var(--bg)' : 'var(--ink-3)',
              fontSize: 11, cursor: 'pointer', fontWeight: sentFilter === f ? 600 : 400,
            }}
          >
            {sentimentLabels[f]}
          </button>
        ))}
      </div>

      {loading && <BtcSkeleton />}
      {!loading && loadErr && (
        <div className="card" style={{ padding: 24, textAlign: 'center', color: 'var(--down)' }}>
          ⚠️ {`Couldn’t load signals — ${loadErr}`}
          <div style={{ marginTop: 10 }}>
            <button className="btn ghost" style={{ fontSize: 12, padding: '6px 14px' }}
              onClick={() => location.reload()}>{isZh ? '重试' : 'Retry'}</button>
          </div>
        </div>
      )}
      {!loading && !loadErr && filtered.length === 0 && (
        <div className="card" style={{ padding: 48, textAlign: 'center', color: 'var(--ink-3)' }}>
          {tab === 'bottom' ? 'No bottom signals yet.' : 'No funding signals yet.'}
          <div style={{ fontSize: 12, marginTop: 6 }}>
            {tab === 'bottom'
              ? 'Intentionally rare — fires only at genuine cycle bottoms.'
              : 'Check the live panel above for current funding state.'}
          </div>
        </div>
      )}
      {!loading && filtered.length > 0 && (
        <div className="post-stream">
          {filtered.map(p => <PostRow key={p.id} post={p} />)}
        </div>
      )}
    </div>
  )
}

// ── Funding rate live panel ─────────────────────────────────────────────────
function FundingPanel({
  isZh,
  initialSnapshot = null,
}: {
  isZh: boolean
  initialSnapshot?: FundingSnapshot | null
}) {
  const [snap, setSnap] = useState<FundingSnapshot | null>(initialSnapshot)
  const [err, setErr] = useState('')

  useEffect(() => {
    let alive = true
    function load() {
      swrFetch(
        'funding-snapshot',
        5 * 60_000, // 5 min — funding cadence is 1–8h, no point polling faster
        () => getFundingSnapshot(),
        fresh => { if (alive) setSnap(fresh) },
      )
        .then(s => { if (alive) { setSnap(s); setErr('') } })
        .catch(e => { if (alive) setErr(e instanceof Error ? e.message : (isZh ? '加载失败' : 'load failed')) })
    }
    load()
    const id = setInterval(load, 5 * 60_000)
    return () => { alive = false; clearInterval(id) }
  }, [isZh])

  if (err) {
    return (
      <div className="card" style={{ padding: 14, color: 'var(--down)', fontSize: 12 }}>
        {`Funding snapshot failed — ${err}`}
      </div>
    )
  }
  if (!snap) {
    return (
      <div className="skeleton-card">
        <div className="skeleton sk-line sk-w-3q" />
        <div className="skeleton sk-title sk-w-half" />
        <div className="skeleton sk-line sk-w-full" />
      </div>
    )
  }
  if (!snap.ok) {
    return (
      <div className="card" style={{ padding: 14, color: 'var(--ink-3)', fontSize: 12 }}>
        {`Funding data unavailable — ${snap.error || 'unknown error'}`}
      </div>
    )
  }

  // Color the cumulative figure by direction + extremity.
  const cum = snap.cum_30d_pct ?? 0
  const thr = snap.extreme_threshold_pct ?? 3
  const extreme = Math.abs(cum) >= thr
  const cumColor = extreme ? (cum > 0 ? 'var(--down)' : 'var(--up)') : 'var(--ink)'

  // Direction hint if extreme (longs paying = SHORT setup; shorts paying = LONG)
  const directionHint = extreme
    ? (cum > 0
        ? 'Longs are crowded; reversal bias is SHORT.'
        : 'Shorts are crowded; reversal bias is LONG.')
    : 'Funding remains inside the normal range.'

  return (
    <div className="card" style={{ padding: 16, marginBottom: 12 }}>
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'baseline',
        flexWrap: 'wrap', gap: 12, marginBottom: 12,
      }}>
        <div style={{ fontSize: 14, fontWeight: 700 }}>
          BTC perp funding · live
        </div>
        <div style={{ fontSize: 11, color: 'var(--ink-4)' }}>
          {`${snap.cadence_hours}h cadence · ${snap.coverage_days}d coverage · ${
            snap.venue ? snap.venue.charAt(0).toUpperCase() + snap.venue.slice(1) : 'Binance'
          }`}
        </div>
      </div>

      <div style={{
        display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(140px, 1fr))',
        gap: 12, marginBottom: 12,
      }}>
        <StatBox
          label="Latest cycle"
          value={snap.latest_rate_pct == null ? '—' : `${snap.latest_rate_pct.toFixed(4)}%`}
          hint="The most recent funding payment, in % per cycle. Positive = longs pay shorts."
        />
        <StatBox
          label="Last 24h avg"
          value={snap.last_24h_avg_pct == null ? '—' : `${snap.last_24h_avg_pct.toFixed(4)}%`}
          hint="Average of the last 24 hours of funding cycles. Smooths out one-off prints."
        />
        <StatBox
          label="30d cumulative"
          value={`${cum >= 0 ? '+' : ''}${cum.toFixed(2)}%`}
          color={cumColor}
          sub={`extreme @ ±${thr}%`}
          hint="Sum of every funding payment over 30 days. Crosses ±3% = one side has been paying for weeks — overcrowded."
        />
        <StatBox
          label="Signal"
          value={snap.signal_fired
            ? '🚨 FIRED'
            : extreme
              ? '⏳ Watching'
              : '✓ Quiet'}
          color={snap.signal_fired ? 'var(--down)' : extreme ? 'var(--amber, #f59e0b)' : 'var(--up)'}
          hint="Quiet = normal range. Watching = extreme funding detected, waiting for mean-revert + price confirm. Fired = trade triggered."
        />
      </div>

      <div style={{
        padding: '8px 12px', borderRadius: 6, fontSize: 12,
        background: extreme ? 'var(--down-soft, rgba(220,38,38,.08))' : 'var(--bg-sunk)',
        color: extreme ? 'var(--down)' : 'var(--ink-3)',
        marginBottom: 12,
      }}>
        {directionHint}
        {snap.debug?.reason && (
          <span style={{ color: 'var(--ink-4)', marginLeft: 8 }}>
            ({String(snap.debug.reason).replaceAll('_', ' ')})
          </span>
        )}
      </div>

      {/* 7-day sparkline removed: the y-range was forced to include the ±threshold
          lines, so in normal regimes the curve rendered as a flat line on the zero
          axis with ~80% of the plot being empty danger-zone shading. The stat boxes
          above (latest / 24h avg / 30d cumulative / signal state) carry the signal. */}
    </div>
  )
}

function StatBox({ label, value, color, sub, hint }: {
  label: string; value: string; color?: string; sub?: string; hint?: string
}) {
  return (
    <div style={{
      padding: 10, background: 'var(--bg-sunk)', borderRadius: 6,
      border: '1px solid var(--line)',
      // The InfoTip bubble overflows the stat box; let it escape.
      overflow: 'visible',
    }}>
      <div style={{ fontSize: 10, color: 'var(--ink-4)', textTransform: 'uppercase',
                    letterSpacing: '.06em', marginBottom: 4,
                    display: 'flex', alignItems: 'center' }}>
        {label}
        {hint && <InfoTip text={hint} placement="top" width={220} />}
      </div>
      <div style={{ fontSize: 16, fontWeight: 700, color: color || 'var(--ink)',
                    fontVariantNumeric: 'tabular-nums' }}>{value}</div>
      {sub && <div style={{ fontSize: 10, color: 'var(--ink-4)', marginTop: 2 }}>{sub}</div>}
    </div>
  )
}

function BtcSkeleton() {
  return (
    <div className="post-stream" style={{ marginTop: 8 }}>
      {Array.from({ length: 3 }).map((_, i) => (
        <div key={i} className="skeleton-card" style={{ marginBottom: 8 }}>
          <div style={{ display: 'flex', gap: 8 }}>
            <div className="skeleton sk-line-sm" style={{ width: 80 }} />
            <div className="skeleton sk-line-sm" style={{ width: 60 }} />
          </div>
          <div className="skeleton sk-title sk-w-3q" />
          <div className="skeleton sk-line sk-w-full" />
          <div className="skeleton sk-line sk-w-half" />
          <div style={{ display: 'flex', gap: 8, marginTop: 4 }}>
            <div className="skeleton sk-line-sm" style={{ width: 56 }} />
            <div className="skeleton sk-line-sm" style={{ width: 80 }} />
          </div>
        </div>
      ))}
    </div>
  )
}
