'use client'

import { useState, useEffect, useMemo } from 'react'
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'
import PageHint from '@/components/ui/PageHint'
import MacroPanel from '@/components/btc/MacroPanel'

/**
 * 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')

  useEffect(() => {
    // BTC on-chain signals update daily — 30 min TTL is safe
    swrFetch(
      'posts-500',
      3 * 60_000,
      () => getPosts(500, 1),
      fresh => setPosts(fresh),
    )
      .then(p => { setPosts(p); setLoadErr('') })
      .catch(e => setLoadErr(e instanceof Error ? e.message : (isZh ? '信号加载失败' : 'Failed to load signals')))
      .finally(() => setLoading(false))
  }, [isZh])

  // Tab-scoped post source. 'bottom' = MVRV/200WMA confluence,
  // 'funding' = funding-rate extreme reversal.
  const tabSource = tab === 'bottom' ? 'btc_bottom_reversal' : 'funding_reversal'
  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>
          <h1 className="page-title">{isZh ? '宏观氛围' : 'Macro Vibes'}</h1>
          {/* PageHint: brand tagline for the page — same across both tabs so
              the "what is this page" answer doesn't shift under the user when
              they click between Bottom / Funding. Tab-specific notes live in
              the section-hint card right below the tab bar. */}
          <PageHint>
            Macro vibes for crypto. Read what&apos;s about to happen before price prints it.
          </PageHint>
        </div>
        <span className="chip"><span className="live-dot" />Live</span>
      </div>

      <SystemControl system="btc" />

      <div className="nav-tabs" style={{
        background: 'var(--bg-sunk)', marginTop: 16, marginBottom: 12,
      }}>
        <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>

      {/* Always-visible per-tab explanation. Was hidden behind a hover
          tooltip on the tab button — users couldn't tell what they were
          about to look at until they explicitly hovered. */}
      {tab === 'bottom' && (
        <div className="section-hint">
          Fires when <strong>≥2 of 3</strong> classic bottom signals agree:{' '}
          <strong>AHR999&nbsp;&lt;&nbsp;0.45</strong> · <strong>price ≤ 200-week MA</strong>
          {' '}· <strong>Pi Cycle Bottom</strong>. Long only, 2–4 fires per cycle.
          Holds up to 18 months with a trailing-stop exit — no take-profit.
        </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 />}
      {tab === 'funding' && (
        <div className="section-hint">
          Mean-reversion against crowded perp positioning. When 30-day cumulative
          funding crosses <strong>±3%</strong> AND the most recent cycles start
          cooling off, the scanner bets against the side that's been paying for
          weeks. Hourly check.
        </div>
      )}

      {/* Old plain-text per-tab description removed — the same content
          now lives in the section-hint block above the tab content. */}

      {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 macro-bottom signals yet.'
            : 'No funding-reversal signals yet.'}
          <div style={{ fontSize: 12, marginTop: 8 }}>
            {tab === 'bottom'
              ? 'This scanner is intentionally rare — only fires at genuine macro bottoms (daily 00:45 UTC).'
              : 'Fires when 30-day cumulative funding exceeds ±3% AND starts mean-reverting. See the live panel above for current 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 · 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?.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?.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>

      {snap.history && snap.history.length > 1 && (
        <FundingSparkline
          history={snap.history}
          cadenceHours={snap.cadence_hours ?? 8}
          extremeCumPct={thr}
          isZh={isZh}
        />
      )}
    </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>
  )
}

// Tiny inline SVG sparkline of the last 7 days of funding cycles.
// `extremeCumPct` is the 30d cumulative threshold (e.g. 3.0). To project it as
// a per-cycle reference line we divide by the number of cycles in 30 days at
// the venue's cadence (24h × 30d / cadence_h). This is the per-cycle rate that
// — sustained for 30 days — would hit the extreme bucket.
function FundingSparkline({ history, cadenceHours, extremeCumPct, isZh }: {
  history: { t: number; rate_pct: number }[]
  cadenceHours: number
  extremeCumPct: number
  isZh: boolean
}) {
  const W = 600, H = 90, PAD = 6
  const cyclesIn30d = Math.max(1, (30 * 24) / Math.max(cadenceHours, 0.5))
  const perCycleThr = extremeCumPct / cyclesIn30d   // e.g. 3% / 90 ≈ 0.033%

  const rates = history.map(h => h.rate_pct)
  // Ensure threshold lines are always visible in the y-range
  const minR = Math.min(...rates, -perCycleThr * 1.2)
  const maxR = Math.max(...rates,  perCycleThr * 1.2)
  const span = maxR - minR || 1
  const x = (i: number) => PAD + (i / (history.length - 1)) * (W - 2 * PAD)
  const y = (r: number) => PAD + (1 - (r - minR) / span) * (H - 2 * PAD)
  const zeroY = y(0)
  const posThrY = y(perCycleThr)
  const negThrY = y(-perCycleThr)
  const path = history.map((h, i) => `${i === 0 ? 'M' : 'L'} ${x(i)} ${y(h.rate_pct)}`).join(' ')
  const last = history[history.length - 1]
  // Color the dot by whether the latest cycle is inside the danger band
  const inDanger = Math.abs(last.rate_pct) >= perCycleThr
  const dotColor = inDanger
    ? (last.rate_pct > 0 ? 'var(--down)' : 'var(--up)')
    : 'var(--amber, #f59e0b)'

  return (
    <div>
      <div style={{
        display: 'flex', justifyContent: 'space-between',
        fontSize: 10, color: 'var(--ink-4)', marginBottom: 4,
      }}>
        <span>{isZh ? '7 日资金费率（单周期 %）' : '7-day funding (per-cycle %)'}</span>
        <span>{isZh ? `危险区间：每周期 ±${perCycleThr.toFixed(3)}%` : `danger band: ±${perCycleThr.toFixed(3)}% / cycle`}</span>
      </div>
      <svg viewBox={`0 0 ${W} ${H}`} style={{ width: '100%', height: H, display: 'block' }}>
        {/* danger zones — shaded above +thr and below -thr */}
        <rect x={PAD} y={PAD} width={W - 2 * PAD} height={Math.max(0, posThrY - PAD)}
              fill="var(--down)" opacity={0.07} />
        <rect x={PAD} y={negThrY} width={W - 2 * PAD} height={Math.max(0, H - PAD - negThrY)}
              fill="var(--up)" opacity={0.07} />

        {/* zero line */}
        <line x1={PAD} x2={W - PAD} y1={zeroY} y2={zeroY}
              stroke="var(--line-2, var(--line))" strokeWidth={1} />
        {/* positive / negative threshold lines */}
        <line x1={PAD} x2={W - PAD} y1={posThrY} y2={posThrY}
              stroke="var(--down)" strokeWidth={1} strokeDasharray="3 3" opacity={0.6} />
        <line x1={PAD} x2={W - PAD} y1={negThrY} y2={negThrY}
              stroke="var(--up)" strokeWidth={1} strokeDasharray="3 3" opacity={0.6} />

        {/* funding curve */}
        <path d={path} fill="none" stroke="var(--amber, #f59e0b)" strokeWidth={1.5} />
        {/* current value dot */}
        <circle cx={x(history.length - 1)} cy={y(last.rate_pct)} r={3.5} fill={dotColor} />
      </svg>
    </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>
  )
}
