'use client'

/**
 * Ticker — horizontal scrolling price tape under the navbar, the way a crypto
 * terminal shows a running market strip. Driven by the shared WebSocket price
 * feed (no new socket). Each asset cell flashes green/red on a price change and
 * shows the live last price.
 *
 * Behaviour notes:
 *  - The strip is duplicated once and translated -50% in a CSS marquee so the
 *    loop is seamless (`ticker-marquee` keyframe in globals.css).
 *  - prefers-reduced-motion disables the scroll (CSS), so the tape becomes a
 *    static, readable row instead of moving.
 *  - The animation is paused on hover so a user can read a specific price.
 *  - Assets with no tick yet render "—" rather than a stale zero.
 */

import { useRef, useState } from 'react'
import { useWsSubscribe } from '@/lib/wsContext'

// Assets the backend streams (see binance ASSET_MAP + hl_price_feed). Order is
// the display order in the tape.
const ASSETS = ['BTC', 'ETH', 'SOL', 'BNB', 'DOGE', 'LINK', 'AAVE', 'TRUMP', 'HYPE'] as const

interface Cell {
  price: number | null
  dir: 'up' | 'down' | null
}

function fmtPrice(p: number): string {
  if (p >= 1000) return '$' + p.toLocaleString('en-US', { maximumFractionDigits: 0 })
  if (p >= 1)    return '$' + p.toLocaleString('en-US', { maximumFractionDigits: 2 })
  return '$' + p.toLocaleString('en-US', { maximumFractionDigits: 4 })
}

export default function Ticker() {
  const [cells, setCells] = useState<Record<string, Cell>>({})
  // Per-asset flash-clear timers so a fast stream doesn't leak setTimeouts.
  const timers = useRef<Record<string, ReturnType<typeof setTimeout>>>({})

  useWsSubscribe('price', (msg) => {
    const m = msg as { asset?: string; price?: number }
    if (!m.asset || typeof m.price !== 'number') return
    const asset = m.asset.toUpperCase()
    if (!ASSETS.includes(asset as (typeof ASSETS)[number])) return

    setCells((prev) => {
      const old = prev[asset]
      const dir: Cell['dir'] =
        old?.price != null && m.price !== old.price
          ? (m.price! > old.price ? 'up' : 'down')
          : old?.dir ?? null
      return { ...prev, [asset]: { price: m.price!, dir } }
    })

    // Clear the flash after 600ms.
    clearTimeout(timers.current[asset])
    timers.current[asset] = setTimeout(() => {
      setCells((prev) => (prev[asset] ? { ...prev, [asset]: { ...prev[asset], dir: null } } : prev))
    }, 600)
  })

  const strip = ASSETS.map((a) => {
    const c = cells[a]
    return (
      <span key={a} className={`ticker-cell ${c?.dir ? `tick-flash-${c.dir}` : ''}`}>
        <span className="ticker-sym">{a}</span>
        <span className="ticker-px">{c?.price != null ? fmtPrice(c.price) : '—'}</span>
        <span className={`ticker-arrow ${c?.dir ?? ''}`} aria-hidden>
          {c?.dir === 'up' ? '▲' : c?.dir === 'down' ? '▼' : ''}
        </span>
      </span>
    )
  })

  return (
    <div className="ticker" role="region" aria-label="Live market prices">
      <div className="ticker-track">
        {strip}
        {/* duplicate for seamless loop */}
        <span aria-hidden style={{ display: 'contents' }}>{strip}</span>
      </div>
    </div>
  )
}
