← Back
β˜†
import { useState, useEffect, useMemo } from 'react'
import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query'
import { Activity, ShieldAlert, ArrowUpRight, ArrowDownRight, Info, AlertTriangle, TrendingUp, TrendingDown, AlignVerticalJustifyCenter, Bell, BellRing, BellOff, Table2, BarChart3 } from 'lucide-react'
import { registerSW } from 'virtual:pwa-register'

// Create a react-query client
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      refetchInterval: 30000, // auto refresh every 30s
      refetchOnWindowFocus: true,
    },
  },
})

// Main App wrapped in QueryProvider
function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Dashboard />
    </QueryClientProvider>
  )
}

// ═══════════════════════════════════════════════════════════════
// P&L CALCULATOR MODAL
// ═══════════════════════════════════════════════════════════════
function PnLCalculator({ isOpen, onClose, prefill }) {
  const [optionType, setOptionType] = useState(prefill?.type || 'CALL')
  const [strike, setStrike] = useState(prefill?.strike || 0)
  const [premium, setPremium] = useState(prefill?.premium || 0) // per-unit premium
  const [qty, setQty] = useState(prefill?.qty || 1) // contracts
  const [spot, setSpot] = useState(prefill?.spot || 0)
  const unit = prefill?.unit || 1 // XRP=100, DOGE=1000, others=1

  // Update when prefill changes
  useEffect(() => {
    if (prefill) {
      setOptionType(prefill.type || 'CALL')
      setStrike(prefill.strike || 0)
      setPremium(prefill.premium || 0)
      setQty(prefill.qty || 1)
      setSpot(prefill.spot || 0)
    }
  }, [prefill])

  if (!isOpen) return null

  const isCall = optionType === 'CALL'
  // Premium is per-unit, breakeven uses per-unit math
  const breakeven = isCall ? strike + premium : strike - premium
  // Total cost = premium_per_unit Γ— unit Γ— qty_contracts
  const maxLoss = premium * unit * qty
  const totalCost = premium * unit * qty

  // Generate P&L at different spot prices
  const spotRange = []
  const center = spot || strike
  const step = center * 0.01 // 1% steps
  for (let i = -15; i <= 15; i++) {
    const s = center + (i * step)
    if (s <= 0) continue
    let pnl
    if (isCall) {
      const intrinsic = Math.max(0, s - strike)
      pnl = (intrinsic - premium) * unit * qty
    } else {
      const intrinsic = Math.max(0, strike - s)
      pnl = (intrinsic - premium) * unit * qty
    }
    spotRange.push({ spot: s, pnl })
  }

  const maxProfit = Math.max(...spotRange.map(r => r.pnl))
  const maxPnL = Math.max(Math.abs(maxProfit), Math.abs(maxLoss))

  // Bar chart helpers
  const barWidth = (pnl) => Math.min(100, Math.abs(pnl) / maxPnL * 100)
  const barColor = (pnl) => pnl >= 0 ? 'bg-green-500' : 'bg-red-500'

  return (
    <div className="fixed inset-0 bg-black/70 backdrop-blur-sm z-50 flex items-center justify-center p-4" onClick={onClose}>
      <div className="bg-darkBg border border-darkBorder rounded-xl max-w-lg w-full max-h-[90vh] overflow-y-auto shadow-2xl" onClick={e => e.stopPropagation()}>
        {/* Header */}
        <div className="flex justify-between items-center px-4 py-3 border-b border-darkBorder">
          <h3 className="text-lg font-bold text-white flex items-center gap-2">πŸ“Š P&L Calculator</h3>
          <button onClick={onClose} className="text-gray-400 hover:text-white text-xl">βœ•</button>
        </div>

        {/* Inputs */}
        <div className="px-4 py-3 grid grid-cols-2 gap-3">
          <div>
            <label className="text-[10px] text-gray-500 uppercase">Type</label>
            <div className="flex gap-1 mt-1">
              <button onClick={() => setOptionType('CALL')}
                className={`flex-1 py-1.5 rounded text-xs font-bold ${isCall ? 'bg-green-600 text-white' : 'bg-darkSurface text-gray-400 border border-darkBorder'}`}>CALL</button>
              <button onClick={() => setOptionType('PUT')}
                className={`flex-1 py-1.5 rounded text-xs font-bold ${!isCall ? 'bg-red-600 text-white' : 'bg-darkSurface text-gray-400 border border-darkBorder'}`}>PUT</button>
            </div>
          </div>
          <div>
            <label className="text-[10px] text-gray-500 uppercase">Qty</label>
            <input type="number" value={qty} onChange={e => setQty(e.target.value === '' ? '' : parseFloat(e.target.value))} onBlur={() => { if (!qty || qty < 0.01) setQty(0.01) }} step="0.01" min="0.01"
              className="w-full mt-1 bg-darkSurface border border-darkBorder rounded px-2 py-1.5 text-white text-sm font-mono" />
          </div>
          <div>
            <label className="text-[10px] text-gray-500 uppercase">Strike ($)</label>
            <input type="number" value={strike} onChange={e => setStrike(parseFloat(e.target.value) || 0)} step="any"
              className="w-full mt-1 bg-darkSurface border border-darkBorder rounded px-2 py-1.5 text-white text-sm font-mono" />
          </div>
          <div>
            <label className="text-[10px] text-gray-500 uppercase">Premium {unit > 1 ? `($/unit, 1ct=${unit})` : '($)'}</label>
            <input type="number" value={premium} onChange={e => setPremium(parseFloat(e.target.value) || 0)} step="any"
              className="w-full mt-1 bg-darkSurface border border-darkBorder rounded px-2 py-1.5 text-white text-sm font-mono" />
          </div>
          <div className="col-span-2">
            <label className="text-[10px] text-gray-500 uppercase">Current Spot ($)</label>
            <input type="number" value={spot} onChange={e => setSpot(parseFloat(e.target.value) || 0)} step="any"
              className="w-full mt-1 bg-darkSurface border border-darkBorder rounded px-2 py-1.5 text-white text-sm font-mono" />
          </div>
        </div>

        {/* Key Metrics */}
        <div className="px-4 py-2 grid grid-cols-3 gap-2 text-xs font-mono">
          <div className="bg-darkSurface rounded p-2 border border-darkBorder text-center">
            <div className="text-gray-500 text-[9px]">BREAKEVEN</div>
            <div className="text-yellow-400 font-bold">${breakeven.toLocaleString(undefined, { maximumFractionDigits: 2 })}</div>
          </div>
          <div className="bg-darkSurface rounded p-2 border border-darkBorder text-center">
            <div className="text-gray-500 text-[9px]">MAX LOSS</div>
            <div className="text-red-400 font-bold">-${maxLoss.toLocaleString(undefined, { maximumFractionDigits: 2 })}</div>
          </div>
          <div className="bg-darkSurface rounded p-2 border border-darkBorder text-center">
            <div className="text-gray-500 text-[9px]">TOTAL COST</div>
            <div className="text-white font-bold">${totalCost.toLocaleString(undefined, { maximumFractionDigits: 2 })}</div>
          </div>
        </div>

        {/* Payoff Diagram (horizontal bar chart) */}
        <div className="px-4 py-3">
          <div className="text-[10px] text-gray-500 uppercase mb-2">Payoff at Expiration</div>
          <div className="space-y-px">
            {spotRange.map((r, i) => {
              const isBreakeven = Math.abs(r.spot - breakeven) < step * 0.6
              const isCurrentSpot = spot > 0 && Math.abs(r.spot - spot) < step * 0.6
              return (
                <div key={i} className={`flex items-center gap-1 text-[10px] font-mono py-0.5 ${isCurrentSpot ? 'bg-blue-500/10 rounded' : ''} ${isBreakeven ? 'bg-yellow-500/10 rounded' : ''}`}>
                  <span className={`w-16 text-right flex-shrink-0 ${isCurrentSpot ? 'text-blue-400 font-bold' : isBreakeven ? 'text-yellow-400' : 'text-gray-500'}`}>
                    ${r.spot >= 1000 ? (r.spot/1000).toFixed(1) + 'K' : r.spot.toFixed(2)}
                    {isCurrentSpot ? ' β—„' : ''}
                  </span>
                  <div className="flex-1 flex items-center h-3">
                    {r.pnl >= 0 ? (
                      <div className="flex items-center w-full">
                        <div className="w-1/2"></div>
                        <div className={`h-2.5 rounded-r ${barColor(r.pnl)}`} style={{ width: `${barWidth(r.pnl) / 2}%` }}></div>
                      </div>
                    ) : (
                      <div className="flex items-center justify-end w-full">
                        <div className={`h-2.5 rounded-l ${barColor(r.pnl)}`} style={{ width: `${barWidth(r.pnl) / 2}%` }}></div>
                        <div className="w-1/2"></div>
                      </div>
                    )}
                  </div>
                  <span className={`w-16 text-right flex-shrink-0 ${r.pnl >= 0 ? 'text-green-400' : 'text-red-400'}`}>
                    {r.pnl >= 0 ? '+' : ''}{r.pnl < 1000 && r.pnl > -1000 ? r.pnl.toFixed(2) : (r.pnl/1000).toFixed(1) + 'K'}
                  </span>
                </div>
              )
            })}
          </div>
          {/* Legend */}
          <div className="flex gap-4 mt-2 text-[9px] text-gray-500">
            <span>β—„ = current spot</span>
            <span className="text-yellow-400/50">β–ˆ = breakeven zone</span>
            <span className="text-green-400/50">β–ˆ = profit</span>
            <span className="text-red-400/50">β–ˆ = loss</span>
          </div>
        </div>
      </div>
    </div>
  )
}

// ═══════════════════════════════════════════════════════════════
// WHALE FLOW FEED
// ═══════════════════════════════════════════════════════════════
function WhaleFlow() {
  const [wfAsset, setWfAsset] = useState('ALL')
  const [minPremium, setMinPremium] = useState(1000)
  const assets = ['ALL', 'BTC', 'ETH', 'SOL', 'BNB', 'XRP', 'DOGE']
  const premiumFilters = [1000, 5000, 10000, 50000]
  const baseUrl = import.meta.env.DEV ? 'http://localhost:8080' : ''

  const { data, isLoading } = useQuery({
    queryKey: ['whaleFlow', wfAsset, minPremium],
    queryFn: async () => {
      const params = new URLSearchParams({ minPremium: minPremium.toString(), limit: '50' })
      if (wfAsset !== 'ALL') params.set('underlying', wfAsset)
      const res = await fetch(`${baseUrl}/api/whale-flow?${params}`)
      if (!res.ok) throw new Error('Failed')
      return res.json()
    },
    refetchInterval: 30000,
  })

  const flows = data?.data || []
  const summary = data?.summary || {}

  const fmtUsd = (n) => {
    if (n >= 1000000) return `$${(n/1000000).toFixed(1)}M`
    if (n >= 1000) return `$${(n/1000).toFixed(1)}K`
    return `$${n?.toFixed(0)}`
  }

  const sizeEmoji = (size) => {
    if (size === 'WHALE') return 'πŸ‹'
    if (size === 'LARGE') return '🦈'
    if (size === 'NOTABLE') return '🐟'
    return 'Β·'
  }

  const sentimentColor = (s) => s === 'BULLISH' ? 'text-green-400' : 'text-red-400'

  return (
    <div>
      {/* Controls */}
      <div className="flex flex-wrap gap-3 mb-4 items-center">
        <div className="flex gap-1 bg-darkSurface p-1 rounded-lg border border-darkBorder">
          {assets.map(a => (
            <button key={a} onClick={() => setWfAsset(a)}
              className={`px-3 py-1 rounded text-xs font-bold transition-colors ${
                wfAsset === a ? 'bg-blue-600 text-white' : 'text-gray-400 hover:text-white'
              }`}>{a}</button>
          ))}
        </div>
        <div className="flex gap-1 bg-darkSurface p-1 rounded-lg border border-darkBorder">
          <span className="text-[10px] text-gray-500 flex items-center px-1">Min:</span>
          {premiumFilters.map(p => (
            <button key={p} onClick={() => setMinPremium(p)}
              className={`px-2 py-1 rounded text-[10px] font-mono transition-colors ${
                minPremium === p ? 'bg-amber-600 text-white' : 'text-gray-400 hover:text-white'
              }`}>{fmtUsd(p)}</button>
          ))}
        </div>
      </div>

      {/* Summary Bar */}
      {summary.totalPremium > 0 && (
        <div className="flex gap-3 mb-4 text-xs font-mono">
          <div className="bg-darkSurface rounded-lg px-3 py-2 border border-darkBorder flex-1 text-center">
            <div className="text-gray-500 text-[9px]">TOTAL FLOW</div>
            <div className="text-white font-bold">{fmtUsd(summary.totalPremium)}</div>
          </div>
          <div className="bg-green-500/10 rounded-lg px-3 py-2 border border-green-500/20 flex-1 text-center">
            <div className="text-green-500/70 text-[9px]">🟒 BULLISH</div>
            <div className="text-green-400 font-bold">{fmtUsd(summary.bullishPremium)}</div>
          </div>
          <div className="bg-red-500/10 rounded-lg px-3 py-2 border border-red-500/20 flex-1 text-center">
            <div className="text-red-500/70 text-[9px]">πŸ”΄ BEARISH</div>
            <div className="text-red-400 font-bold">{fmtUsd(summary.bearishPremium)}</div>
          </div>
          <div className="bg-darkSurface rounded-lg px-3 py-2 border border-darkBorder flex-1 text-center">
            <div className="text-gray-500 text-[9px]">BULL/BEAR</div>
            <div className={`font-bold ${summary.bullBearRatio > 1 ? 'text-green-400' : 'text-red-400'}`}>
              {summary.bullBearRatio?.toFixed(2)}x
            </div>
          </div>
        </div>
      )}

      {isLoading && (
        <div className="flex justify-center py-12">
          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-amber-500"></div>
        </div>
      )}

      {!isLoading && flows.length > 0 && (
        <div className="overflow-x-auto rounded-lg border border-darkBorder">
          <table className="w-full text-[11px] font-mono border-collapse">
            <thead>
              <tr className="bg-darkSurface text-gray-400 border-b border-darkBorder">
                <th className="px-2 py-2 text-left">Size</th>
                <th className="px-2 py-2 text-left">Asset</th>
                <th className="px-2 py-2 text-left">Contract</th>
                <th className="px-2 py-2 text-right">Premium</th>
                <th className="px-2 py-2 text-right">Vol</th>
                <th className="px-2 py-2 text-right">Price</th>
                <th className="px-2 py-2 text-right">V/OI</th>
                <th className="px-2 py-2 text-right">IV</th>
                <th className="px-2 py-2 text-right">Ξ”</th>
                <th className="px-2 py-2 text-right">DTE</th>
                <th className="px-2 py-2 text-center">Dir</th>
              </tr>
            </thead>
            <tbody>
              {flows.map((f, i) => (
                <tr key={i} className={`border-b border-darkBorder/30 hover:bg-darkSurface/50 ${
                  f.size === 'WHALE' ? 'bg-amber-500/5' : ''
                }`}>
                  <td className="px-2 py-1.5">{sizeEmoji(f.size)}</td>
                  <td className="px-2 py-1.5 text-white font-bold">{f.underlying}</td>
                  <td className="px-2 py-1.5">
                    <span className={f.type === 'CALL' ? 'text-green-400' : 'text-red-400'}>{f.type}</span>
                    <span className="text-gray-400 ml-1">${f.strike.toLocaleString()}</span>
                    <span className="text-gray-600 ml-1">{f.expiry.substring(2,4)}/{f.expiry.substring(4,6)}</span>
                  </td>
                  <td className="px-2 py-1.5 text-right">
                    <span className={`font-bold ${f.size === 'WHALE' ? 'text-amber-400' : f.size === 'LARGE' ? 'text-amber-300' : 'text-white'}`}>
                      {fmtUsd(f.premium)}
                    </span>
                  </td>
                  <td className="px-2 py-1.5 text-right text-gray-300">{f.volume.toFixed(1)}</td>
                  <td className="px-2 py-1.5 text-right text-gray-400">${f.lastPrice < 1 ? f.lastPrice.toFixed(4) : f.lastPrice.toFixed(2)}</td>
                  <td className="px-2 py-1.5 text-right">
                    <span className={f.voiRatio > 5 ? 'text-amber-400 font-bold' : 'text-gray-500'}>
                      {f.voiRatio > 100 ? '∞' : f.voiRatio.toFixed(1)}x
                    </span>
                  </td>
                  <td className="px-2 py-1.5 text-right text-gray-400">{f.iv ? (f.iv * 100).toFixed(0) + '%' : 'β€”'}</td>
                  <td className="px-2 py-1.5 text-right text-gray-300">{f.delta?.toFixed(3) || 'β€”'}</td>
                  <td className="px-2 py-1.5 text-right">
                    <span className={f.dte <= 3 ? 'text-red-400' : f.dte <= 7 ? 'text-yellow-400' : 'text-gray-400'}>
                      {f.dte}d
                    </span>
                  </td>
                  <td className="px-2 py-1.5 text-center">
                    <span className={`px-1.5 py-0.5 rounded text-[9px] font-bold ${
                      f.sentiment === 'BULLISH' ? 'bg-green-500/20 text-green-400' : 'bg-red-500/20 text-red-400'
                    }`}>
                      {f.sentiment === 'BULLISH' ? '🟒' : 'πŸ”΄'}
                    </span>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      {!isLoading && flows.length === 0 && (
        <div className="text-center text-gray-500 py-12 bg-darkSurface rounded-xl border border-darkBorder">
          No whale activity above {fmtUsd(minPremium)} threshold. Try lowering the filter.
        </div>
      )}
    </div>
  )
}

// ═══════════════════════════════════════════════════════════════
// OPTIONS CHAIN VIEW
// ═══════════════════════════════════════════════════════════════
function ChainView() {
  const [chainAsset, setChainAsset] = useState('BTC')
  const [chainExpiry, setChainExpiry] = useState(null)
  const assets = ['BTC', 'ETH', 'SOL', 'BNB', 'XRP', 'DOGE']

  const baseUrl = import.meta.env.DEV ? 'http://localhost:8080' : ''

  const { data, isLoading } = useQuery({
    queryKey: ['chain', chainAsset, chainExpiry],
    queryFn: async () => {
      const params = new URLSearchParams({ underlying: chainAsset })
      if (chainExpiry) params.set('expiry', chainExpiry)
      const res = await fetch(`${baseUrl}/api/chain?${params}`)
      if (!res.ok) throw new Error('Failed to fetch chain')
      return res.json()
    },
    refetchInterval: 30000,
  })

  // When asset changes, reset expiry to let API pick nearest
  useEffect(() => { setChainExpiry(null) }, [chainAsset])

  // When data arrives and no expiry set, default to first
  useEffect(() => {
    if (data?.expiry && !chainExpiry) setChainExpiry(data.expiry)
  }, [data?.expiry])

  const chain = data?.chain || []
  const spot = data?.spotApprox || 0

  // Find ATM index for scroll-to
  const atmIndex = useMemo(() => {
    return chain.findIndex(r => r.moneyness === 'ATM')
  }, [chain])

  // Auto-scroll to ATM on load
  useEffect(() => {
    if (atmIndex >= 0) {
      const el = document.getElementById(`strike-${atmIndex}`)
      if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' })
    }
  }, [atmIndex, chainExpiry])

  const fmtNum = (n, d = 2) => n != null ? Number(n).toFixed(d) : 'β€”'
  const fmtK = (n) => n >= 1000 ? `${(n/1000).toFixed(1)}K` : n?.toString() || '0'

  // Color for IV relative (green = low, red = high)
  const ivColor = (iv) => {
    if (!iv) return 'text-gray-500'
    if (iv < 0.3) return 'text-green-400'
    if (iv < 0.6) return 'text-yellow-400'
    return 'text-red-400'
  }

  // Highlight rows near ATM
  const rowBg = (row) => {
    if (row.moneyness === 'ATM') return 'bg-blue-500/10 border-l-2 border-r-2 border-blue-500/50'
    return 'hover:bg-darkSurface/50'
  }

  // OI bar width (relative to max)
  const maxOI = useMemo(() => Math.max(...chain.map(r => r.totalOI), 1), [chain])

  return (
    <div>
      {/* Controls */}
      <div className="flex flex-wrap gap-3 mb-4 items-center">
        {/* Asset selector */}
        <div className="flex gap-1 bg-darkSurface p-1 rounded-lg border border-darkBorder">
          {assets.map(a => (
            <button key={a} onClick={() => setChainAsset(a)}
              className={`px-3 py-1 rounded text-xs font-bold transition-colors ${
                chainAsset === a ? 'bg-blue-600 text-white' : 'text-gray-400 hover:text-white'
              }`}>{a}</button>
          ))}
        </div>

        {/* Expiry selector */}
        {data?.expiries && (
          <div className="flex gap-1 bg-darkSurface p-1 rounded-lg border border-darkBorder overflow-x-auto max-w-[500px]">
            {data.expiries.map(exp => {
              // Calculate DTE for label
              const y = 2000 + parseInt(exp.substring(0, 2))
              const m = parseInt(exp.substring(2, 4)) - 1
              const d = parseInt(exp.substring(4, 6))
              const dte = Math.max(0, Math.ceil((new Date(Date.UTC(y, m, d, 8)) - Date.now()) / 86400000))
              return (
                <button key={exp} onClick={() => setChainExpiry(exp)}
                  className={`px-2 py-1 rounded text-[10px] font-mono whitespace-nowrap transition-colors ${
                    chainExpiry === exp ? 'bg-purple-600 text-white' : 'text-gray-400 hover:text-white'
                  }`}>
                  {exp.substring(2,4)}/{exp.substring(4,6)} <span className="text-gray-500">({dte}d)</span>
                </button>
              )
            })}
          </div>
        )}

        {/* Info badges */}
        {data && (
          <div className="flex gap-2 text-[10px] text-gray-500">
            <span>Spot β‰ˆ <span className="text-white font-bold">${spot?.toLocaleString()}</span></span>
            <span>DTE <span className="text-white font-bold">{data.dte}d</span></span>
            <span>Strikes <span className="text-white font-bold">{data.strikesCount}</span></span>
          </div>
        )}
      </div>

      {isLoading && (
        <div className="flex justify-center py-12">
          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500"></div>
        </div>
      )}

      {!isLoading && chain.length > 0 && (
        <div className="overflow-x-auto rounded-lg border border-darkBorder">
          <table className="w-full text-[11px] font-mono border-collapse">
            <thead>
              <tr className="bg-darkSurface text-gray-400 border-b border-darkBorder">
                {/* CALLS side */}
                <th className="px-2 py-2 text-right text-green-400/70">Vol</th>
                <th className="px-2 py-2 text-right text-green-400/70">OI</th>
                <th className="px-2 py-2 text-right text-green-400/70">IV</th>
                <th className="px-2 py-2 text-right text-green-400/70">Ξ”</th>
                <th className="px-2 py-2 text-right text-green-400/70">Bid</th>
                <th className="px-2 py-2 text-right text-green-400/70">Ask</th>
                {/* Strike */}
                <th className="px-3 py-2 text-center bg-darkBg font-bold text-white border-x border-darkBorder">Strike</th>
                {/* PUTS side */}
                <th className="px-2 py-2 text-left text-red-400/70">Bid</th>
                <th className="px-2 py-2 text-left text-red-400/70">Ask</th>
                <th className="px-2 py-2 text-left text-red-400/70">Ξ”</th>
                <th className="px-2 py-2 text-left text-red-400/70">IV</th>
                <th className="px-2 py-2 text-left text-red-400/70">OI</th>
                <th className="px-2 py-2 text-left text-red-400/70">Vol</th>
              </tr>
              <tr className="bg-darkSurface/50 text-[9px] text-gray-500 border-b border-darkBorder">
                <td colSpan="6" className="text-center py-0.5 text-green-500/50">── CALLS ──</td>
                <td className="text-center bg-darkBg border-x border-darkBorder"></td>
                <td colSpan="6" className="text-center py-0.5 text-red-500/50">── PUTS ──</td>
              </tr>
            </thead>
            <tbody>
              {chain.map((row, i) => {
                const c = row.call
                const p = row.put
                const isAtm = row.moneyness === 'ATM'
                const isCallItm = row.moneyness === 'ITM_CALL'
                const isPutItm = row.moneyness === 'ITM_PUT'

                return (
                  <tr key={row.strike} id={`strike-${i}`}
                    className={`border-b border-darkBorder/30 transition-colors ${rowBg(row)} ${isAtm ? 'font-bold' : ''}`}>
                    {/* CALL side */}
                    <td className={`px-2 py-1.5 text-right ${isCallItm ? 'bg-green-500/5' : ''}`}>
                      <span className={c?.volume > 0 ? 'text-green-400' : 'text-gray-600'}>{fmtK(c?.volume)}</span>
                    </td>
                    <td className={`px-2 py-1.5 text-right ${isCallItm ? 'bg-green-500/5' : ''}`}>
                      <span className="text-gray-400">{fmtK(c?.openInterest)}</span>
                    </td>
                    <td className={`px-2 py-1.5 text-right ${isCallItm ? 'bg-green-500/5' : ''}`}>
                      <span className={ivColor(c?.iv)}>{c?.iv ? (c.iv * 100).toFixed(0) + '%' : 'β€”'}</span>
                    </td>
                    <td className={`px-2 py-1.5 text-right ${isCallItm ? 'bg-green-500/5' : ''}`}>
                      <span className="text-gray-300">{c?.delta != null ? fmtNum(c.delta, 3) : 'β€”'}</span>
                    </td>
                    <td className={`px-2 py-1.5 text-right ${isCallItm ? 'bg-green-500/5' : ''}`}>
                      <span className="text-green-400">{c ? '$' + fmtNum(c.markPrice, c.markPrice < 1 ? 4 : 2) : 'β€”'}</span>
                    </td>
                    <td className={`px-2 py-1.5 text-right ${isCallItm ? 'bg-green-500/5' : ''}`}>
                      <span className="text-green-300">{c ? '$' + fmtNum(c.lastPrice, c.lastPrice < 1 ? 4 : 2) : 'β€”'}</span>
                    </td>

                    {/* STRIKE center */}
                    <td className={`px-3 py-1.5 text-center bg-darkBg border-x border-darkBorder ${isAtm ? 'text-blue-400 text-sm' : 'text-white'}`}>
                      {row.strike.toLocaleString()}
                      {isAtm && <span className="ml-1 text-[8px] text-blue-500">ATM</span>}
                    </td>

                    {/* PUT side */}
                    <td className={`px-2 py-1.5 text-left ${isPutItm ? 'bg-red-500/5' : ''}`}>
                      <span className="text-red-400">{p ? '$' + fmtNum(p.markPrice, p.markPrice < 1 ? 4 : 2) : 'β€”'}</span>
                    </td>
                    <td className={`px-2 py-1.5 text-left ${isPutItm ? 'bg-red-500/5' : ''}`}>
                      <span className="text-red-300">{p ? '$' + fmtNum(p.lastPrice, p.lastPrice < 1 ? 4 : 2) : 'β€”'}</span>
                    </td>
                    <td className={`px-2 py-1.5 text-left ${isPutItm ? 'bg-red-500/5' : ''}`}>
                      <span className="text-gray-300">{p?.delta != null ? fmtNum(p.delta, 3) : 'β€”'}</span>
                    </td>
                    <td className={`px-2 py-1.5 text-left ${isPutItm ? 'bg-red-500/5' : ''}`}>
                      <span className={ivColor(p?.iv)}>{p?.iv ? (p.iv * 100).toFixed(0) + '%' : 'β€”'}</span>
                    </td>
                    <td className={`px-2 py-1.5 text-left ${isPutItm ? 'bg-red-500/5' : ''}`}>
                      <span className="text-gray-400">{fmtK(p?.openInterest)}</span>
                    </td>
                    <td className={`px-2 py-1.5 text-left ${isPutItm ? 'bg-red-500/5' : ''}`}>
                      <span className={p?.volume > 0 ? 'text-red-400' : 'text-gray-600'}>{fmtK(p?.volume)}</span>
                    </td>
                  </tr>
                )
              })}
            </tbody>
          </table>
        </div>
      )}

      {!isLoading && chain.length === 0 && (
        <div className="text-center text-gray-500 py-12 bg-darkSurface rounded-xl border border-darkBorder">
          No options data for {chainAsset}. Try another asset.
        </div>
      )}
    </div>
  )
}

// ═══════════════════════════════════════════════════════════════
// IV SURFACE / TERM STRUCTURE
// ═══════════════════════════════════════════════════════════════
function IvSurface() {
  const [asset, setAsset] = useState('BTC')
  const [optType, setOptType] = useState('CALL')
  const [selectedExpiry, setSelectedExpiry] = useState(null)
  const assets = ['BTC', 'ETH', 'SOL', 'BNB', 'XRP', 'DOGE']

  const { data, isLoading } = useQuery({
    queryKey: ['iv-surface', asset, optType],
    queryFn: () => fetch(`/api/iv-surface?underlying=${asset}&type=${optType}`)
      .then(r => r.json()),
    refetchInterval: 30000,
  })

  const smiles = data?.smiles || []
  const termStructure = data?.termStructure || []
  const spot = data?.spot || 0
  const shape = data?.shape || 'FLAT'

  // Pick which expiry smiles to show (up to 4)
  const visibleSmiles = selectedExpiry
    ? smiles.filter(s => s.expiry === selectedExpiry)
    : smiles.slice(0, 4)

  // Colors for expiry lines
  const lineColors = ['#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', '#ec4899']

  // Find IV range across visible smiles for chart scaling β€” add 10% padding
  const allIvs = visibleSmiles.flatMap(s => s.points.map(p => p.iv))
  const rawIvMin = allIvs.length ? Math.min(...allIvs) : 0
  const rawIvMax = allIvs.length ? Math.max(...allIvs) : 1
  const ivPad = (rawIvMax - rawIvMin) * 0.1 || 0.01
  const ivMin = rawIvMin - ivPad
  const ivMax = rawIvMax + ivPad
  const ivRange = ivMax - ivMin || 0.01

  // Term structure chart scaling
  const tsIvs = termStructure.map(t => t.atmIv)
  const tsMin = tsIvs.length ? Math.min(...tsIvs) : 0
  const tsMax = tsIvs.length ? Math.max(...tsIvs) : 1
  const tsRange = tsMax - tsMin || 0.01

  const shapeLabel = {
    CONTANGO: { text: 'Contango (normal)', color: 'text-green-400', desc: 'Π”Π°Π»ΡŒΠ½ΠΈΠ΅ Π΄ΠΎΡ€ΠΎΠΆΠ΅ β€” Ρ€Ρ‹Π½ΠΎΠΊ спокоСн' },
    BACKWARDATION: { text: 'Backwardation (inverted)', color: 'text-red-400', desc: 'Π‘Π»ΠΈΠΆΠ½ΠΈΠ΅ Π΄ΠΎΡ€ΠΎΠΆΠ΅ β€” Ρ€Ρ‹Π½ΠΎΠΊ Π½Π΅Ρ€Π²Π½ΠΈΡ‡Π°Π΅Ρ‚' },
    FLAT: { text: 'Flat', color: 'text-gray-400', desc: 'IV одинаковая ΠΏΠΎ срокам' },
  }[shape] || { text: shape, color: 'text-gray-400', desc: '' }

  return (
    <div>
      {/* Controls */}
      <div className="flex flex-wrap gap-3 mb-4">
        <div className="flex gap-1 bg-darkSurface p-1 rounded-lg border border-darkBorder">
          {assets.map(a => (
            <button key={a} onClick={() => { setAsset(a); setSelectedExpiry(null) }}
              className={`px-3 py-1.5 rounded-md text-xs font-medium transition-colors ${
                asset === a ? 'bg-blue-600 text-white' : 'text-gray-400 hover:text-white'
              }`}>{a}</button>
          ))}
        </div>
        <div className="flex gap-1 bg-darkSurface p-1 rounded-lg border border-darkBorder">
          <button onClick={() => setOptType('CALL')}
            className={`px-3 py-1.5 rounded-md text-xs font-medium ${
              optType === 'CALL' ? 'bg-green-600 text-white' : 'text-gray-400 hover:text-white'
            }`}>Calls</button>
          <button onClick={() => setOptType('PUT')}
            className={`px-3 py-1.5 rounded-md text-xs font-medium ${
              optType === 'PUT' ? 'bg-red-600 text-white' : 'text-gray-400 hover:text-white'
            }`}>Puts</button>
        </div>
        {smiles.length > 0 && (
          <select value={selectedExpiry || ''}
            onChange={e => setSelectedExpiry(e.target.value || null)}
            className="bg-darkSurface text-gray-300 text-xs border border-darkBorder rounded-lg px-3 py-1.5">
            <option value="">All expiries (top 4)</option>
            {smiles.map(s => (
              <option key={s.expiry} value={s.expiry}>
                {s.expiry.substring(2,4)}/{s.expiry.substring(4,6)} ({s.dte}d) β€” {s.points.length} strikes
              </option>
            ))}
          </select>
        )}
      </div>

      {isLoading && (
        <div className="flex justify-center items-center h-48">
          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500"></div>
        </div>
      )}

      {!isLoading && (
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">

          {/* IV SMILE CHART */}
          <div className="bg-darkSurface rounded-xl p-4 border border-darkBorder">
            <h3 className="text-white font-bold mb-1">IV Smile / Skew</h3>
            <p className="text-gray-500 text-xs mb-3">
              IV ΠΏΠΎ страйкам β€” ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΊΠ°ΠΊ Ρ€Ρ‹Π½ΠΎΠΊ ΠΎΡ†Π΅Π½ΠΈΠ²Π°Π΅Ρ‚ риски Π½Π° Ρ€Π°Π·Π½Ρ‹Ρ… уровнях Ρ†Π΅Π½Ρ‹
            </p>
            {visibleSmiles.length === 0 ? (
              <div className="text-gray-500 text-center py-8">No IV data</div>
            ) : (() => {
              // Compute unified strike range across all visible smiles
              const allStrikes = visibleSmiles.flatMap(s => s.points.map(p => p.strike))
              const strikeMin = Math.min(...allStrikes)
              const strikeMax = Math.max(...allStrikes)
              const sRange = strikeMax - strikeMin || 1
              // X-axis labels: 5 evenly spaced strikes
              const fmtStrike = (v) => v >= 1000 ? `$${(v / 1000).toFixed(0)}K` : `$${v.toFixed(0)}`
              const xLabels = [0, 0.25, 0.5, 0.75, 1].map(pct => fmtStrike(strikeMin + pct * sRange))
              return (
              <div className="relative" style={{ height: '300px' }}>
                {/* Y axis labels */}
                <div className="absolute left-0 top-0 bottom-6 w-10 flex flex-col justify-between text-[9px] text-gray-500 pr-1 text-right">
                  <span>{(ivMax * 100).toFixed(0)}%</span>
                  <span>{((ivMin + ivRange * 0.75) * 100).toFixed(0)}%</span>
                  <span>{((ivMin + ivRange * 0.5) * 100).toFixed(0)}%</span>
                  <span>{((ivMin + ivRange * 0.25) * 100).toFixed(0)}%</span>
                  <span>{(ivMin * 100).toFixed(0)}%</span>
                </div>
                {/* Chart area β€” div clips overflow on mobile */}
                <div className="absolute left-10 top-0 right-0 bottom-6 overflow-hidden rounded">
                <svg className="w-full h-full" viewBox="0 0 600 270" preserveAspectRatio="none">
                  {/* Grid lines */}
                  {[0, 0.25, 0.5, 0.75, 1].map(pct => (
                    <line key={pct} x1="0" y1={270 - pct * 260} x2="600" y2={270 - pct * 260}
                      stroke="#374151" strokeWidth="0.5" strokeDasharray="4,4" />
                  ))}
                  {/* Spot price vertical line */}
                  {spot > 0 && (() => {
                    const x = ((spot - strikeMin) / sRange) * 600
                    if (x > 0 && x < 600) {
                      return <line x1={x} y1="0" x2={x} y2="270" stroke="#6b7280" strokeWidth="1" strokeDasharray="6,3" />
                    }
                    return null
                  })()}
                  {/* IV curves per expiry β€” unified X scale */}
                  {visibleSmiles.map((smile, idx) => {
                    const pts = smile.points
                    if (pts.length < 2) return null
                    const pathD = pts.map((p, i) => {
                      const x = ((p.strike - strikeMin) / sRange) * 600
                      const y = 270 - ((p.iv - ivMin) / ivRange) * 260
                      return `${i === 0 ? 'M' : 'L'} ${x} ${y}`
                    }).join(' ')
                    return <path key={smile.expiry} d={pathD} fill="none"
                      stroke={lineColors[idx % lineColors.length]} strokeWidth="2.5" />
                  })}
                </svg>
                </div>
                {/* X axis labels (strikes) */}
                <div className="absolute left-10 right-0 bottom-0 flex justify-between text-[9px] text-gray-500 px-1">
                  {xLabels.map((label, i) => <span key={i}>{label}</span>)}
                </div>
                {/* Legend */}
                <div className="absolute right-1 top-1 bg-darkBg/80 rounded px-1.5 py-1 flex flex-col gap-0.5">
                  {visibleSmiles.map((s, i) => (
                    <div key={s.expiry} className="flex items-center gap-1 text-[9px]">
                      <div className="w-2.5 h-0.5 rounded" style={{ backgroundColor: lineColors[i % lineColors.length] }} />
                      <span className="text-gray-400">{s.expiry.substring(2,4)}/{s.expiry.substring(4,6)} ({s.dte}d)</span>
                    </div>
                  ))}
                </div>
              </div>
              )
            })()}
            {spot > 0 && <div className="text-[9px] text-gray-500 mt-1">Spot: ${spot.toLocaleString()} (dashed line) | X = Strike price</div>}
          </div>

          {/* TERM STRUCTURE CHART */}
          <div className="bg-darkSurface rounded-xl p-4 border border-darkBorder">
            <h3 className="text-white font-bold mb-1">
              Term Structure
              <span className={`ml-2 text-xs font-normal ${shapeLabel.color}`}>{shapeLabel.text}</span>
            </h3>
            <p className="text-gray-500 text-xs mb-3">
              ATM IV ΠΏΠΎ срокам экспирации β€” {shapeLabel.desc}
            </p>
            {termStructure.length === 0 ? (
              <div className="text-gray-500 text-center py-8">No term structure data</div>
            ) : (
              <div className="overflow-x-auto">
                {/* Bar chart β€” scrollable on mobile */}
                <div className="flex items-end gap-2 pb-1" style={{ height: '240px', minWidth: `${Math.max(termStructure.length * 52, 300)}px` }}>
                  {termStructure.map((t, i) => {
                    const pct = tsRange > 0 ? (t.atmIv - tsMin) / tsRange : 0.5
                    const height = 30 + pct * 170
                    const isMin = t.atmIv === tsMin
                    const isMax = t.atmIv === tsMax
                    return (
                      <div key={t.expiry} className="flex flex-col items-center gap-1" style={{ width: '44px', flexShrink: 0 }}>
                        <span className={`text-[9px] ${isMax ? 'text-red-400 font-bold' : isMin ? 'text-green-400 font-bold' : 'text-gray-400'}`}>
                          {(t.atmIv * 100).toFixed(1)}%
                        </span>
                        <div
                          className={`w-8 rounded-t ${
                            i === 0 ? 'bg-blue-500' : shape === 'BACKWARDATION' ? 'bg-red-500/60' : 'bg-green-500/60'
                          }`}
                          style={{ height: `${height}px` }}
                          title={`ATM IV ${(t.atmIv * 100).toFixed(2)}% | Strike $${t.atmStrike?.toLocaleString()}`}
                        />
                        <div className="text-center leading-tight">
                          <div className="text-[9px] text-gray-300">
                            {t.expiry.substring(2,4)}/{t.expiry.substring(4,6)}
                          </div>
                          <div className="text-[8px] text-gray-500">{t.dte}d</div>
                        </div>
                      </div>
                    )
                  })}
                </div>
              </div>
            )}
          </div>
        </div>
      )}

      {/* Educational tooltip */}
      <div className="mt-4 bg-darkSurface rounded-xl p-3 border border-darkBorder text-xs text-gray-400">
        <strong className="text-gray-300">Как Ρ‡ΠΈΡ‚Π°Ρ‚ΡŒ:</strong>
        <span className="ml-1">
          <strong>IV Smile:</strong> U-образная кривая = Ρ€Ρ‹Π½ΠΎΠΊ боится Ρ€Π΅Π·ΠΊΠΈΡ… Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠΉ Π² ΠΎΠ±Π΅ стороны.
          Бкос Π²ΠΏΡ€Π°Π²ΠΎ = страх роста, Π²Π»Π΅Π²ΠΎ = страх падСния.
          <strong className="ml-2">Term Structure:</strong> Contango (Π·Π΅Π»Ρ‘Π½Ρ‹ΠΉ) = Π½ΠΎΡ€ΠΌΠ°, Ρ€Ρ‹Π½ΠΎΠΊ спокоСн.
          Backwardation (красный) = Ρ€Ρ‹Π½ΠΎΠΊ ΠΆΠ΄Ρ‘Ρ‚ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ БЕЙЧАБ β†’ Π±Π»ΠΈΠΆΠ½ΠΈΠ΅ ΠΎΠΏΡ†ΠΈΠΎΠ½Ρ‹ Π΄ΠΎΡ€ΠΎΠΆΠ΅.
        </span>
      </div>
    </div>
  )
}

// ═══════════════════════════════════════════════════════════════
// TRADING TAB β€” Positions, Orders, Account
// ═══════════════════════════════════════════════════════════════
function TradingTab() {
  const baseUrl = import.meta.env.DEV ? 'http://localhost:8080' : ''
  const [statsPeriod, setStatsPeriod] = useState(null) // null = ALL

  const { data: posData, isLoading: posLoading, refetch: refetchPos } = useQuery({
    queryKey: ['tradingPositions'],
    queryFn: async () => {
      const res = await fetch(`${baseUrl}/api/trading/positions`)
      if (!res.ok) throw new Error('Failed')
      return res.json()
    },
    refetchInterval: 15000,
  })

  const { data: ordersData, refetch: refetchOrders } = useQuery({
    queryKey: ['tradingOrders'],
    queryFn: async () => {
      const res = await fetch(`${baseUrl}/api/trading/orders`)
      if (!res.ok) throw new Error('Failed')
      return res.json()
    },
    refetchInterval: 15000,
  })

  const { data: statusData } = useQuery({
    queryKey: ['tradingStatus'],
    queryFn: async () => {
      const res = await fetch(`${baseUrl}/api/trading/status`)
      if (!res.ok) throw new Error('Failed')
      return res.json()
    },
    staleTime: 30000,
  })

  const { data: statsData, refetch: refetchStats } = useQuery({
    queryKey: ['tradingStats', statsPeriod],
    queryFn: async () => {
      const params = statsPeriod ? `&days=${statsPeriod}` : ''
      const res = await fetch(`${baseUrl}/api/trading/stats?_=1${params}`)
      if (!res.ok) throw new Error('Failed')
      return res.json()
    },
    refetchInterval: 60000,
  })

  const { data: journalData, refetch: refetchJournal } = useQuery({
    queryKey: ['tradingJournal', statsPeriod],
    queryFn: async () => {
      const params = statsPeriod ? `&days=${statsPeriod}` : ''
      const res = await fetch(`${baseUrl}/api/trading/journal?_=1${params}&limit=50`)
      if (!res.ok) throw new Error('Failed')
      return res.json()
    },
    refetchInterval: 60000,
  })

  const [syncing, setSyncing] = useState(false)
  const handleSync = async () => {
    setSyncing(true)
    try {
      await fetch(`${baseUrl}/api/trading/sync`, { method: 'POST' })
      refetchStats()
      refetchJournal()
      refetchPos()
    } catch (e) { /* ignore */ }
    setSyncing(false)
  }

  const positions = posData?.data || []
  const orders = ordersData?.data || []
  const account = statusData?.data?.account || {}
  const usdtBal = account.usdtBalance
  const stats = statsData?.data || null

  const cancelOrder = async (symbol, orderId) => {
    await fetch(`${baseUrl}/api/trading/order?symbol=${symbol}&orderId=${orderId}`, { method: 'DELETE' })
    refetchOrders()
  }

  const fmtPrice = (v) => {
    const n = parseFloat(v)
    if (isNaN(n)) return '-'
    return n >= 100 ? n.toLocaleString(undefined, { maximumFractionDigits: 2 }) : n.toFixed(4)
  }

  const fmtHold = (mins) => {
    if (!mins) return '-'
    if (mins < 60) return `${mins}m`
    if (mins < 1440) return `${Math.round(mins / 60)}h`
    return `${(mins / 1440).toFixed(1)}d`
  }

  const periodBtns = [
    { label: '7D', value: 7 },
    { label: '30D', value: 30 },
    { label: 'ALL', value: null },
  ]

  return (
    <div>
      {/* ── Stats Bar ── */}
      {stats && stats.totalTrades > 0 && (
        <div className="mb-4">
          <div className="flex items-center justify-between mb-2">
            <h3 className="text-white font-bold text-sm">Performance</h3>
            <div className="flex gap-1">
              {periodBtns.map(b => (
                <button key={b.label} onClick={() => setStatsPeriod(b.value)}
                  className={`px-2 py-0.5 rounded text-[10px] font-mono transition-colors ${statsPeriod === b.value ? 'bg-orange-600 text-white' : 'text-gray-500 hover:text-white bg-darkSurface border border-darkBorder'}`}>
                  {b.label}
                </button>
              ))}
            </div>
          </div>

          {/* Row 1: Core metrics */}
          <div className="grid grid-cols-3 sm:grid-cols-6 gap-2 mb-2">
            <div className="bg-darkSurface rounded-lg px-2 py-1.5 border border-darkBorder text-center">
              <div className="text-gray-500 text-[9px]">TOTAL P&L</div>
              <div className={`font-bold text-xs font-mono ${stats.totalPnl >= 0 ? 'text-green-400' : 'text-red-400'}`}>
                {stats.totalPnl >= 0 ? '+' : ''}${stats.totalPnl.toFixed(2)}
              </div>
            </div>
            <div className="bg-darkSurface rounded-lg px-2 py-1.5 border border-darkBorder text-center">
              <div className="text-gray-500 text-[9px]">WIN RATE</div>
              <div className={`font-bold text-xs font-mono ${stats.winRate >= 50 ? 'text-green-400' : 'text-red-400'}`}>
                {stats.winRate}%
              </div>
            </div>
            <div className="bg-darkSurface rounded-lg px-2 py-1.5 border border-darkBorder text-center">
              <div className="text-gray-500 text-[9px]">TRADES</div>
              <div className="text-white font-bold text-xs font-mono">{stats.wins}W / {stats.losses}L</div>
            </div>
            <div className="bg-darkSurface rounded-lg px-2 py-1.5 border border-darkBorder text-center">
              <div className="text-gray-500 text-[9px]">AVG WIN</div>
              <div className="text-green-400 font-bold text-xs font-mono">+${stats.avgWin.toFixed(2)}</div>
            </div>
            <div className="bg-darkSurface rounded-lg px-2 py-1.5 border border-darkBorder text-center">
              <div className="text-gray-500 text-[9px]">AVG LOSS</div>
              <div className="text-red-400 font-bold text-xs font-mono">${stats.avgLoss.toFixed(2)}</div>
            </div>
            <div className="bg-darkSurface rounded-lg px-2 py-1.5 border border-darkBorder text-center">
              <div className="text-gray-500 text-[9px]">PROFIT FACTOR</div>
              <div className={`font-bold text-xs font-mono ${stats.profitFactor >= 1 ? 'text-green-400' : 'text-red-400'}`}>
                {stats.profitFactor >= 999 ? '∞' : stats.profitFactor.toFixed(2)}
              </div>
            </div>
          </div>

          {/* Row 2: Extended metrics */}
          <div className="grid grid-cols-2 sm:grid-cols-5 gap-2">
            <div className="bg-darkSurface rounded-lg px-2 py-1.5 border border-darkBorder text-center">
              <div className="text-gray-500 text-[9px]">BEST TRADE</div>
              <div className="text-green-400 font-bold text-[10px] font-mono truncate">
                {stats.bestTrade ? `${stats.bestTrade.symbol.split('-')[0]} +$${stats.bestTrade.pnl.toFixed(2)}` : '-'}
              </div>
            </div>
            <div className="bg-darkSurface rounded-lg px-2 py-1.5 border border-darkBorder text-center">
              <div className="text-gray-500 text-[9px]">WORST TRADE</div>
              <div className="text-red-400 font-bold text-[10px] font-mono truncate">
                {stats.worstTrade ? `${stats.worstTrade.symbol.split('-')[0]} $${stats.worstTrade.pnl.toFixed(2)}` : '-'}
              </div>
            </div>
            <div className="bg-darkSurface rounded-lg px-2 py-1.5 border border-darkBorder text-center">
              <div className="text-gray-500 text-[9px]">STREAK</div>
              <div className={`font-bold text-xs font-mono ${stats.currentStreakType === 'WIN' ? 'text-green-400' : 'text-red-400'}`}>
                {stats.currentStreak}{stats.currentStreakType === 'WIN' ? 'W' : 'L'}
              </div>
            </div>
            <div className="bg-darkSurface rounded-lg px-2 py-1.5 border border-darkBorder text-center">
              <div className="text-gray-500 text-[9px]">MAX STREAKS</div>
              <div className="text-white font-bold text-[10px] font-mono">
                <span className="text-green-400">{stats.winStreak}W</span> / <span className="text-red-400">{stats.lossStreak}L</span>
              </div>
            </div>
            <div className="bg-darkSurface rounded-lg px-2 py-1.5 border border-darkBorder text-center">
              <div className="text-gray-500 text-[9px]">AVG HOLD</div>
              <div className="text-white font-bold text-xs font-mono">{fmtHold(stats.avgHoldMinutes)}</div>
            </div>
          </div>
        </div>
      )}

      {/* Account Summary */}
      {usdtBal && (
        <div className="flex gap-3 mb-4 text-xs font-mono">
          <div className="bg-darkSurface rounded-lg px-3 py-2 border border-darkBorder flex-1 text-center">
            <div className="text-gray-500 text-[9px]">BALANCE</div>
            <div className="text-white font-bold">${parseFloat(usdtBal.marginBalance || usdtBal.balance || 0).toFixed(2)}</div>
          </div>
          <div className="bg-darkSurface rounded-lg px-3 py-2 border border-darkBorder flex-1 text-center">
            <div className="text-gray-500 text-[9px]">AVAILABLE</div>
            <div className="text-green-400 font-bold">${parseFloat(usdtBal.available || usdtBal.availableBalance || 0).toFixed(2)}</div>
          </div>
          <div className="bg-darkSurface rounded-lg px-3 py-2 border border-darkBorder flex-1 text-center">
            <div className="text-gray-500 text-[9px]">POSITIONS</div>
            <div className="text-white font-bold">{positions.length}</div>
          </div>
          <div className="bg-darkSurface rounded-lg px-3 py-2 border border-darkBorder flex-1 text-center">
            <div className="text-gray-500 text-[9px]">OPEN ORDERS</div>
            <div className="text-white font-bold">{orders.length}</div>
          </div>
        </div>
      )}

      {/* Open Positions */}
      <div className="mb-6">
        <div className="flex items-center justify-between mb-2">
          <h3 className="text-white font-bold text-sm">Open Positions</h3>
          <button onClick={() => refetchPos()} className="text-[10px] text-gray-500 hover:text-white">↻ Refresh</button>
        </div>

        {posLoading && <div className="flex justify-center py-8"><div className="animate-spin rounded-full h-6 w-6 border-b-2 border-orange-500"></div></div>}

        {!posLoading && positions.length === 0 && (
          <div className="text-center py-8 text-gray-600 text-sm">No open positions</div>
        )}

        {positions.length > 0 && (
          <div className="overflow-x-auto rounded-lg border border-darkBorder">
            <table className="w-full text-[11px] font-mono border-collapse">
              <thead>
                <tr className="bg-darkSurface text-gray-400 border-b border-darkBorder">
                  <th className="px-2 py-2 text-left">Symbol</th>
                  <th className="px-2 py-2 text-right">Qty</th>
                  <th className="px-2 py-2 text-right">Entry</th>
                  <th className="px-2 py-2 text-right">Mark</th>
                  <th className="px-2 py-2 text-right">PnL</th>
                  <th className="px-2 py-2 text-right">ROI%</th>
                </tr>
              </thead>
              <tbody>
                {positions.map((p, i) => {
                  const qty = parseFloat(p.quantity || 0)
                  const entry = parseFloat(p.entryPrice || 0)
                  const mark = parseFloat(p.markPrice || p.markValue || 0)
                  const pnl = parseFloat(p.unrealizedPNL || p.unrealizedPnL || 0)
                  const roi = entry > 0 ? ((mark - entry) / entry * 100) : 0
                  return (
                    <tr key={i} className="border-b border-darkBorder/30 hover:bg-darkSurface/50">
                      <td className="px-2 py-1.5 text-white font-bold">{p.symbol}</td>
                      <td className={`px-2 py-1.5 text-right ${qty > 0 ? 'text-green-400' : 'text-red-400'}`}>{qty}</td>
                      <td className="px-2 py-1.5 text-right text-gray-300">{fmtPrice(entry)}</td>
                      <td className="px-2 py-1.5 text-right text-white">{fmtPrice(mark)}</td>
                      <td className={`px-2 py-1.5 text-right font-bold ${pnl >= 0 ? 'text-green-400' : 'text-red-400'}`}>
                        {pnl >= 0 ? '+' : ''}{pnl.toFixed(2)}
                      </td>
                      <td className={`px-2 py-1.5 text-right ${roi >= 0 ? 'text-green-400' : 'text-red-400'}`}>
                        {roi >= 0 ? '+' : ''}{roi.toFixed(1)}%
                      </td>
                    </tr>
                  )
                })}
              </tbody>
            </table>
          </div>
        )}
      </div>

      {/* Open Orders */}
      <div>
        <div className="flex items-center justify-between mb-2">
          <h3 className="text-white font-bold text-sm">Open Orders</h3>
          <button onClick={() => refetchOrders()} className="text-[10px] text-gray-500 hover:text-white">↻ Refresh</button>
        </div>

        {orders.length === 0 && (
          <div className="text-center py-8 text-gray-600 text-sm">No open orders</div>
        )}

        {orders.length > 0 && (
          <div className="overflow-x-auto rounded-lg border border-darkBorder">
            <table className="w-full text-[11px] font-mono border-collapse">
              <thead>
                <tr className="bg-darkSurface text-gray-400 border-b border-darkBorder">
                  <th className="px-2 py-2 text-left">Symbol</th>
                  <th className="px-2 py-2 text-center">Side</th>
                  <th className="px-2 py-2 text-right">Qty</th>
                  <th className="px-2 py-2 text-right">Price</th>
                  <th className="px-2 py-2 text-right">Filled</th>
                  <th className="px-2 py-2 text-center">Action</th>
                </tr>
              </thead>
              <tbody>
                {orders.map((o, i) => (
                  <tr key={i} className="border-b border-darkBorder/30 hover:bg-darkSurface/50">
                    <td className="px-2 py-1.5 text-white font-bold">{o.symbol}</td>
                    <td className={`px-2 py-1.5 text-center font-bold ${o.side === 'BUY' ? 'text-green-400' : 'text-red-400'}`}>{o.side}</td>
                    <td className="px-2 py-1.5 text-right text-gray-300">{o.quantity}</td>
                    <td className="px-2 py-1.5 text-right text-white">{fmtPrice(o.price)}</td>
                    <td className="px-2 py-1.5 text-right text-gray-400">{o.executedQty || 0}/{o.quantity}</td>
                    <td className="px-2 py-1.5 text-center">
                      <button onClick={() => cancelOrder(o.symbol, o.orderId)}
                        className="px-2 py-0.5 bg-red-600/20 border border-red-500/30 rounded text-red-400 text-[10px] hover:bg-red-600/40 transition-colors">
                        Cancel
                      </button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>

      {/* ── Trade Journal ── */}
      <div className="mt-6">
        <div className="flex items-center justify-between mb-2">
          <h3 className="text-white font-bold text-sm">Trade Journal</h3>
          <button onClick={handleSync} disabled={syncing}
            className="text-[10px] text-gray-500 hover:text-white disabled:opacity-50 flex items-center gap-1">
            {syncing ? <span className="animate-spin">⟳</span> : '⟳'} Sync Binance
          </button>
        </div>

        {(!journalData?.data?.trades || journalData.data.trades.length === 0) && (
          <div className="text-center py-6 text-gray-600 text-sm border border-dashed border-darkBorder rounded-lg">
            No closed trades yet. Close a position and hit Sync.
          </div>
        )}

        {journalData?.data?.trades?.length > 0 && (
          <div className="overflow-x-auto rounded-lg border border-darkBorder">
            <table className="w-full text-[11px] font-mono border-collapse">
              <thead>
                <tr className="bg-darkSurface text-gray-400 border-b border-darkBorder">
                  <th className="px-2 py-2 text-left">Date</th>
                  <th className="px-2 py-2 text-left">Asset</th>
                  <th className="px-2 py-2 text-center">Type</th>
                  <th className="px-2 py-2 text-right">Strike</th>
                  <th className="px-2 py-2 text-right">Entry</th>
                  <th className="px-2 py-2 text-right">Exit</th>
                  <th className="px-2 py-2 text-right">P&L</th>
                  <th className="px-2 py-2 text-right">ROI%</th>
                  <th className="px-2 py-2 text-center">Exit</th>
                  <th className="px-2 py-2 text-right">Hold</th>
                </tr>
              </thead>
              <tbody>
                {journalData.data.trades.map((t, i) => (
                  <tr key={t.id || i} className="border-b border-darkBorder/30 hover:bg-darkSurface/50">
                    <td className="px-2 py-1.5 text-gray-400">
                      {new Date(t.exitTime).toLocaleDateString('en-GB', { day: '2-digit', month: 'short' })}
                    </td>
                    <td className="px-2 py-1.5 text-white font-bold">{t.underlying}</td>
                    <td className={`px-2 py-1.5 text-center ${t.optionType === 'CALL' ? 'text-green-400' : 'text-red-400'}`}>
                      {t.optionType === 'CALL' ? 'C' : 'P'}
                    </td>
                    <td className="px-2 py-1.5 text-right text-gray-300">
                      {t.strike >= 1000 ? t.strike.toLocaleString() : t.strike}
                    </td>
                    <td className="px-2 py-1.5 text-right text-gray-300">${t.entryPrice}</td>
                    <td className="px-2 py-1.5 text-right text-white">${t.exitPrice}</td>
                    <td className={`px-2 py-1.5 text-right font-bold ${t.pnl >= 0 ? 'text-green-400' : 'text-red-400'}`}>
                      {t.pnl >= 0 ? '+' : ''}${t.pnl.toFixed(2)}
                    </td>
                    <td className={`px-2 py-1.5 text-right ${t.roi >= 0 ? 'text-green-400' : 'text-red-400'}`}>
                      {t.roi >= 0 ? '+' : ''}{t.roi.toFixed(0)}%
                    </td>
                    <td className="px-2 py-1.5 text-center">
                      {t.exitReason === 'TP_HIT' ? <span className="text-green-400 text-[10px]">TP</span>
                       : t.exitReason === 'SL_HIT' ? <span className="text-red-400 text-[10px]">SL</span>
                       : t.exitReason === 'EXPIRED_WORTHLESS' ? <span className="text-orange-400 text-[10px]">EXP-0</span>
                       : t.exitReason === 'EXERCISED' ? <span className="text-cyan-400 text-[10px]">EXERC</span>
                       : t.exitReason === 'MANUAL_CLOSE' ? <span className="text-gray-400 text-[10px]">MANUAL</span>
                       : t.status === 'EXPIRED' ? <span className="text-orange-400 text-[10px]">EXP</span>
                       : <span className="text-gray-600 text-[10px]">-</span>}
                    </td>
                    <td className="px-2 py-1.5 text-right text-gray-400">{fmtHold(t.holdMinutes)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
            {journalData.data.total > journalData.data.trades.length && (
              <div className="text-center py-2 text-gray-500 text-[10px]">
                Showing {journalData.data.trades.length} of {journalData.data.total} trades
              </div>
            )}
          </div>
        )}
      </div>
    </div>
  )
}

// ═══════════════════════════════════════════════════════════════
// CUSTOM ALERTS TAB
// ═══════════════════════════════════════════════════════════════
function CustomAlerts() {
  const baseUrl = import.meta.env.DEV ? 'http://localhost:8080' : ''
  const [showForm, setShowForm] = useState(false)
  const [editingAlert, setEditingAlert] = useState(null)
  const [form, setForm] = useState({ name: '', underlying: 'BTC', metric: 'iv_rank', condition: 'lt', threshold: '', cooldownMinutes: 30, telegramEnabled: true, pushEnabled: true })
  const [expandedId, setExpandedId] = useState(null)

  // Fetch alerts
  const { data: alertsData, isLoading, refetch } = useQuery({
    queryKey: ['customAlerts'],
    queryFn: async () => {
      const res = await fetch(`${baseUrl}/api/custom-alerts`)
      if (!res.ok) throw new Error('Failed')
      return res.json()
    },
    refetchInterval: 30000,
  })

  // Fetch available metrics
  const { data: metricsData } = useQuery({
    queryKey: ['alertMetrics'],
    queryFn: async () => {
      const res = await fetch(`${baseUrl}/api/custom-alerts/metrics`)
      if (!res.ok) throw new Error('Failed')
      return res.json()
    },
    staleTime: Infinity,
  })

  // Fetch trigger history for expanded alert
  const { data: triggerData } = useQuery({
    queryKey: ['alertTriggers', expandedId],
    queryFn: async () => {
      if (!expandedId) return null
      const res = await fetch(`${baseUrl}/api/custom-alerts/${expandedId}/triggers?limit=10`)
      if (!res.ok) throw new Error('Failed')
      return res.json()
    },
    enabled: !!expandedId,
    refetchInterval: 30000,
  })

  const alerts = alertsData?.data || []
  const metrics = metricsData?.data?.metrics || []
  const conditions = metricsData?.data?.conditions || []
  const underlyings = metricsData?.data?.underlyings || ['BTC', 'ETH', 'SOL', 'DOGE', 'XRP', 'BNB', 'ALL']

  const condLabels = { gt: '>', lt: '<', gte: '>=', lte: '<=', eq: '=', crosses_above: 'Crosses Above', crosses_below: 'Crosses Below' }
  const metricLabel = (id) => metrics.find(m => m.id === id)?.label || id
  const metricUnit = (id) => metrics.find(m => m.id === id)?.unit || ''

  // API helpers
  const apiCall = async (url, method = 'GET', body = null) => {
    const opts = { method, headers: { 'Content-Type': 'application/json' } }
    if (body) opts.body = JSON.stringify(body)
    const res = await fetch(`${baseUrl}${url}`, opts)
    return res.json()
  }

  const handleCreate = async () => {
    if (!form.name || form.threshold === '') return
    const body = { ...form, threshold: parseFloat(form.threshold) }
    if (editingAlert) {
      await apiCall(`/api/custom-alerts/${editingAlert.id}`, 'PUT', body)
    } else {
      await apiCall('/api/custom-alerts', 'POST', body)
    }
    setShowForm(false)
    setEditingAlert(null)
    setForm({ name: '', underlying: 'BTC', metric: 'iv_rank', condition: 'lt', threshold: '', cooldownMinutes: 30, telegramEnabled: true, pushEnabled: true })
    refetch()
  }

  const handleToggle = async (id) => {
    await apiCall(`/api/custom-alerts/${id}/toggle`, 'POST')
    refetch()
  }

  const handleDelete = async (id) => {
    if (!confirm('Delete this alert?')) return
    await apiCall(`/api/custom-alerts/${id}`, 'DELETE')
    refetch()
  }

  const handleEdit = (alert) => {
    setForm({
      name: alert.name,
      underlying: alert.underlying,
      metric: alert.metric,
      condition: alert.condition,
      threshold: alert.threshold,
      cooldownMinutes: alert.cooldownMinutes,
      telegramEnabled: alert.telegramEnabled,
      pushEnabled: alert.pushEnabled,
    })
    setEditingAlert(alert)
    setShowForm(true)
  }

  const timeSince = (dateStr) => {
    if (!dateStr) return 'never'
    const diff = Date.now() - new Date(dateStr).getTime()
    const mins = Math.floor(diff / 60000)
    if (mins < 1) return 'just now'
    if (mins < 60) return `${mins}m ago`
    const hrs = Math.floor(mins / 60)
    if (hrs < 24) return `${hrs}h ago`
    return `${Math.floor(hrs / 24)}d ago`
  }

  return (
    <div>
      {/* Header */}
      <div className="flex items-center justify-between mb-4">
        <div className="text-sm text-gray-400">
          {alerts.length} alert{alerts.length !== 1 ? 's' : ''} configured
          <span className="text-gray-600 ml-2">({alerts.filter(a => a.enabled).length} active)</span>
        </div>
        <button onClick={() => { setShowForm(!showForm); setEditingAlert(null); setForm({ name: '', underlying: 'BTC', metric: 'iv_rank', condition: 'lt', threshold: '', cooldownMinutes: 30, telegramEnabled: true, pushEnabled: true }) }}
          className="flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium bg-blue-600 hover:bg-blue-700 text-white transition-colors">
          {showForm ? 'βœ• Cancel' : '+ New Alert'}
        </button>
      </div>

      {/* Create/Edit Form */}
      {showForm && (
        <div className="bg-darkSurface border border-darkBorder rounded-xl p-4 mb-4">
          <h3 className="text-white font-bold text-sm mb-3">{editingAlert ? 'Edit Alert' : 'Create Alert'}</h3>
          <div className="grid grid-cols-2 md:grid-cols-3 gap-3">
            {/* Name */}
            <div className="col-span-2 md:col-span-3">
              <label className="text-[10px] text-gray-500 uppercase">Alert Name</label>
              <input type="text" value={form.name} onChange={e => setForm({...form, name: e.target.value})} placeholder="e.g. BTC IV Rank Low"
                className="w-full mt-1 bg-darkBg border border-darkBorder rounded px-3 py-2 text-white text-sm" />
            </div>

            {/* Underlying */}
            <div>
              <label className="text-[10px] text-gray-500 uppercase">Asset</label>
              <select value={form.underlying} onChange={e => setForm({...form, underlying: e.target.value})}
                className="w-full mt-1 bg-darkBg border border-darkBorder rounded px-3 py-2 text-white text-sm">
                {underlyings.map(u => <option key={u} value={u}>{u}</option>)}
              </select>
            </div>

            {/* Metric */}
            <div>
              <label className="text-[10px] text-gray-500 uppercase">Metric</label>
              <select value={form.metric} onChange={e => setForm({...form, metric: e.target.value})}
                className="w-full mt-1 bg-darkBg border border-darkBorder rounded px-3 py-2 text-white text-sm">
                {metrics.map(m => <option key={m.id} value={m.id}>{m.label}</option>)}
              </select>
            </div>

            {/* Condition */}
            <div>
              <label className="text-[10px] text-gray-500 uppercase">Condition</label>
              <select value={form.condition} onChange={e => setForm({...form, condition: e.target.value})}
                className="w-full mt-1 bg-darkBg border border-darkBorder rounded px-3 py-2 text-white text-sm">
                {conditions.map(c => <option key={c} value={c}>{condLabels[c] || c}</option>)}
              </select>
            </div>

            {/* Threshold */}
            <div>
              <label className="text-[10px] text-gray-500 uppercase">Threshold {metricUnit(form.metric) ? `(${metricUnit(form.metric)})` : ''}</label>
              <input type="number" value={form.threshold} onChange={e => setForm({...form, threshold: e.target.value})} step="any" placeholder="20"
                className="w-full mt-1 bg-darkBg border border-darkBorder rounded px-3 py-2 text-white text-sm font-mono" />
            </div>

            {/* Cooldown */}
            <div>
              <label className="text-[10px] text-gray-500 uppercase">Cooldown (min)</label>
              <input type="number" value={form.cooldownMinutes} onChange={e => setForm({...form, cooldownMinutes: parseInt(e.target.value) || 30})} min="1"
                className="w-full mt-1 bg-darkBg border border-darkBorder rounded px-3 py-2 text-white text-sm font-mono" />
            </div>

            {/* Delivery toggles */}
            <div className="flex items-end gap-4 pb-1">
              <label className="flex items-center gap-2 text-xs text-gray-300 cursor-pointer">
                <input type="checkbox" checked={form.telegramEnabled} onChange={e => setForm({...form, telegramEnabled: e.target.checked})}
                  className="accent-blue-500" />
                Telegram
              </label>
              <label className="flex items-center gap-2 text-xs text-gray-300 cursor-pointer">
                <input type="checkbox" checked={form.pushEnabled} onChange={e => setForm({...form, pushEnabled: e.target.checked})}
                  className="accent-blue-500" />
                Push
              </label>
            </div>
          </div>

          {/* Description hint */}
          {form.metric && (
            <div className="mt-2 text-[11px] text-gray-500 italic">
              {metrics.find(m => m.id === form.metric)?.description}
            </div>
          )}

          {/* Preview */}
          {form.name && form.threshold !== '' && (
            <div className="mt-3 bg-darkBg rounded-lg px-3 py-2 border border-darkBorder/50 text-xs text-gray-300">
              Preview: <span className="text-white font-bold">{form.underlying}</span> {metricLabel(form.metric)} <span className="text-yellow-400">{condLabels[form.condition]}</span> <span className="text-white font-mono">{form.threshold}{metricUnit(form.metric)}</span>
            </div>
          )}

          <button onClick={handleCreate}
            className="mt-3 w-full py-2 rounded-lg text-sm font-bold bg-green-600 hover:bg-green-700 text-white transition-colors">
            {editingAlert ? 'Save Changes' : 'Create Alert'}
          </button>
        </div>
      )}

      {/* Loading */}
      {isLoading && (
        <div className="flex justify-center py-12">
          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500"></div>
        </div>
      )}

      {/* Empty state */}
      {!isLoading && alerts.length === 0 && !showForm && (
        <div className="text-center py-16 text-gray-500">
          <Bell size={48} className="mx-auto mb-3 opacity-30" />
          <p className="text-lg font-medium">No alerts configured</p>
          <p className="text-sm mt-1">Create your first alert to get notified when market conditions change</p>
        </div>
      )}

      {/* Alert Cards */}
      {!isLoading && alerts.length > 0 && (
        <div className="space-y-2">
          {alerts.map(alert => (
            <div key={alert.id} className={`bg-darkSurface border rounded-xl overflow-hidden transition-colors ${
              alert.enabled ? 'border-darkBorder' : 'border-darkBorder/50 opacity-60'
            }`}>
              {/* Main row */}
              <div className="flex items-center gap-3 px-4 py-3">
                {/* Toggle */}
                <button onClick={() => handleToggle(alert.id)}
                  className={`flex-shrink-0 w-10 h-5 rounded-full relative transition-colors ${alert.enabled ? 'bg-green-600' : 'bg-gray-700'}`}>
                  <div className={`absolute top-0.5 w-4 h-4 rounded-full bg-white transition-transform ${alert.enabled ? 'left-5' : 'left-0.5'}`} />
                </button>

                {/* Info */}
                <div className="flex-1 min-w-0" onClick={() => setExpandedId(expandedId === alert.id ? null : alert.id)}
                  style={{ cursor: 'pointer' }}>
                  <div className="flex items-center gap-2">
                    <span className="text-white font-bold text-sm truncate">{alert.name}</span>
                    <span className="text-[10px] px-1.5 py-0.5 rounded bg-blue-600/20 text-blue-400 font-mono">{alert.underlying}</span>
                  </div>
                  <div className="text-[11px] text-gray-400 mt-0.5 font-mono">
                    {metricLabel(alert.metric)} {condLabels[alert.condition]} {alert.threshold}{metricUnit(alert.metric)}
                  </div>
                </div>

                {/* Delivery indicators */}
                <div className="flex gap-1 flex-shrink-0">
                  {alert.telegramEnabled && <span title="Telegram" className="text-[10px] bg-blue-500/20 text-blue-400 px-1.5 py-0.5 rounded">TG</span>}
                  {alert.pushEnabled && <span title="Push" className="text-[10px] bg-purple-500/20 text-purple-400 px-1.5 py-0.5 rounded">Push</span>}
                </div>

                {/* Last triggered */}
                <div className="flex-shrink-0 text-right">
                  <div className="text-[10px] text-gray-500">Last trigger</div>
                  <div className={`text-[11px] font-mono ${alert.lastTriggeredAt ? 'text-yellow-400' : 'text-gray-600'}`}>
                    {timeSince(alert.lastTriggeredAt)}
                  </div>
                </div>

                {/* Actions */}
                <div className="flex gap-1 flex-shrink-0">
                  <button onClick={() => handleEdit(alert)} className="text-gray-500 hover:text-white p-1 transition-colors" title="Edit">✏️</button>
                  <button onClick={() => handleDelete(alert.id)} className="text-gray-500 hover:text-red-400 p-1 transition-colors" title="Delete">πŸ—‘οΈ</button>
                </div>
              </div>

              {/* Expanded: Trigger History */}
              {expandedId === alert.id && (
                <div className="border-t border-darkBorder/50 px-4 py-3 bg-darkBg/50">
                  <div className="text-[10px] text-gray-500 uppercase mb-2">Recent Triggers</div>
                  {triggerData?.data?.length > 0 ? (
                    <div className="space-y-1.5">
                      {triggerData.data.map((t, i) => (
                        <div key={i} className="flex items-center gap-3 text-[11px] font-mono">
                          <span className="text-gray-500">{new Date(t.createdAt).toLocaleString()}</span>
                          <span className="text-yellow-400">value: {typeof t.value === 'number' ? t.value.toFixed(2) : t.value}</span>
                        </div>
                      ))}
                    </div>
                  ) : (
                    <div className="text-[11px] text-gray-600 italic">No triggers yet</div>
                  )}
                </div>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  )
}

// ═══════════════════════════════════════════════════════════════
// SIGNALS DASHBOARD (existing)
// ═══════════════════════════════════════════════════════════════
function TradeModal({ signal: sig, tradeResult, setTradeResult, onClose }) {
  const t = sig.trade || {}
  const isCombo = !!(t.contracts && t.contracts.length > 1)
  const contracts = isCombo ? t.contracts : [{ symbol: t.symbol || t.contract || sig.parameters?.symbol || '', entry: t.entry || parseFloat(sig.parameters?.costUsd) || 0, type: t.action?.includes('CALL') ? 'CALL' : 'PUT', tpPct: t.target?.returnPct || 100, qty: t.qty || 0.01 }]

  const defaultQty = contracts[0]?.qty || t.qty || 0.01
  const [qty, setQtyLocal] = useState(defaultQty)
  const [submitting, setSubmitting] = useState(false)
  const [legResults, setLegResults] = useState([])

  const totalCost = contracts.reduce((s, c) => s + (c.entry || 0) * qty, 0)
  const sizing = t.sizing || null

  const handleExecute = async () => {
    setSubmitting(true)
    setTradeResult(null)
    setLegResults([])
    const base = import.meta.env.DEV ? 'http://localhost:8080' : ''
    const results = []

    for (const c of contracts) {
      try {
        const tpPct = c.tpPct || t.target?.returnPct || 100
        const body = { symbol: c.symbol, side: 'BUY', quantity: qty, price: c.entry, tpPct }
        const res = await fetch(`${base}/api/trading/order`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(body),
        })
        const json = await res.json()
        results.push({ symbol: c.symbol, type: c.type, ...json })
      } catch (err) {
        results.push({ symbol: c.symbol, type: c.type, success: false, error: err.message })
      }
    }

    setLegResults(results)
    const allOk = results.every(r => r.success)
    setTradeResult({ success: allOk, data: { legs: results } })
    if (allOk) setTimeout(() => onClose(), 3000)
    setSubmitting(false)
  }

  return (
    <div className="fixed inset-0 bg-black/70 backdrop-blur-sm z-50 flex items-center justify-center p-4" onClick={onClose}>
      <div className="bg-darkBg border border-darkBorder rounded-xl max-w-md w-full shadow-2xl" onClick={e => e.stopPropagation()}>
        <div className="flex justify-between items-center px-4 py-3 border-b border-darkBorder">
          <h3 className="text-lg font-bold text-white flex items-center gap-2">⚑ Execute {isCombo ? 'Combo' : 'Trade'}</h3>
          <button onClick={onClose} className="text-gray-400 hover:text-white text-xl">βœ•</button>
        </div>
        <div className="px-4 py-3 space-y-3">
          <div className="bg-darkSurface rounded-lg p-3 border border-darkBorder">
            <div className="flex items-center gap-2 mb-1">
              <span className={`text-xs font-bold px-2 py-0.5 rounded ${sig.direction === 'BULLISH' ? 'bg-green-600/20 text-green-400' : sig.direction === 'BEARISH' ? 'bg-red-600/20 text-red-400' : 'bg-blue-600/20 text-blue-400'}`}>
                {sig.direction}
              </span>
              <span className="text-white font-bold text-sm">{sig.underlying} β€” {sig.strategy}</span>
            </div>
            {contracts.map((c, i) => (
              <div key={i} className="flex justify-between text-[11px] text-gray-400 font-mono mt-1">
                <span>{c.type === 'CALL' ? 'πŸ“ˆ' : 'πŸ“‰'} {c.type} {c.symbol}</span>
                <span className="text-white">${c.entry?.toFixed(4)}</span>
              </div>
            ))}
          </div>

          {/* Qty input β€” pre-filled from sizing */}
          <div>
            <label className="text-[10px] text-gray-500 uppercase">Quantity (both legs)</label>
            <input type="number" value={qty} onChange={e => setQtyLocal(e.target.value === '' ? '' : parseFloat(e.target.value))} onBlur={() => { if (!qty || qty < 0.01) setQtyLocal(0.01) }} step="0.01" min="0.01"
              className="w-full mt-1 bg-darkSurface border border-darkBorder rounded px-2 py-1.5 text-white text-sm font-mono" />
            {sizing && (
              <div className="text-[10px] text-gray-500 mt-1">
                Suggested: {defaultQty} ({sizing.riskPct}% of ${sizing.balance} = ${sizing.riskAmount} risk)
              </div>
            )}
          </div>

          {/* Cost + TP summary per leg */}
          <div className="bg-darkSurface rounded-lg px-3 py-2 border border-darkBorder text-xs font-mono space-y-1">
            <div className="flex justify-between text-gray-400">
              <span>Total Cost (max loss):</span>
              <span className="text-white font-bold">${totalCost.toFixed(4)}</span>
            </div>
            {sizing && sizing.riskOfDeposit > 5 && (
              <div className="text-yellow-400">⚠️ {sizing.riskOfDeposit.toFixed(1)}% of deposit β€” high risk!</div>
            )}
            {contracts.map((c, i) => {
              const tp = c.tpPct || t.target?.returnPct || 100
              return (
                <div key={i} className="flex justify-between text-gray-400 pt-1 border-t border-darkBorder/30">
                  <span>{c.type} TP ({tp}%):</span>
                  <span className="text-green-400">${(c.entry * (1 + tp / 100)).toFixed(4)}</span>
                </div>
              )
            })}
            <div className="flex justify-between text-gray-400 pt-1 border-t border-darkBorder/30">
              <span>Profit if winning leg hits TP:</span>
              <span className="text-green-400 font-bold">+${(contracts[0].entry * qty * (contracts[0].tpPct || t.target?.returnPct || 100) / 100).toFixed(4)}</span>
            </div>
          </div>

          {/* Results per leg */}
          {legResults.length > 0 && legResults.map((r, i) => (
            <div key={i} className={`rounded-lg px-3 py-2 text-sm ${r.success ? 'bg-green-500/10 border border-green-500/30 text-green-400' : 'bg-red-500/10 border border-red-500/30 text-red-400'}`}>
              {r.success ? `βœ… ${r.type} placed: ${r.symbol}` : `❌ ${r.type}: ${r.error}`}
            </div>
          ))}

          <button onClick={handleExecute} disabled={submitting}
            className={`w-full py-2.5 rounded-lg text-sm font-bold transition-colors ${
              submitting ? 'bg-gray-700 text-gray-500' : 'bg-green-600 hover:bg-green-700 text-white'
            }`}>
            {submitting ? '⏳ Placing...' : `⚑ BUY ${isCombo ? `${contracts.length} legs` : contracts[0]?.symbol} + auto TP`}
          </button>
          <div className="text-[10px] text-gray-600 text-center">Premium = max loss. TP SELL auto-placed on fill per leg.</div>
        </div>
      </div>
    </div>
  )
}

// ─── BACKTEST TAB ──────────────────────────────────────────
function SortHeader({ label, field, sort, setSort, align = 'right' }) {
  const active = sort.field === field
  const arrow = active ? (sort.dir === 'asc' ? ' β–²' : ' β–Ό') : ''
  return (
    <th className={`${align === 'left' ? 'text-left' : 'text-right'} px-3 py-2 cursor-pointer select-none hover:text-gray-300 transition-colors ${active ? 'text-cyan-400' : ''}`}
        onClick={() => setSort(s => s.field === field ? { field, dir: s.dir === 'asc' ? 'desc' : 'asc' } : { field, dir: 'desc' })}>
      {label}{arrow}
    </th>
  )
}

function BacktestTab() {
  const [days, setDays] = useState(30)
  const [sigFilter, setSigFilter] = useState({ strategy: '', underlying: '', outcome: '' })
  const [sigPage, setSigPage] = useState(0)
  const [stratSort, setStratSort] = useState({ field: 'total', dir: 'desc' })
  const [assetSort, setAssetSort] = useState({ field: 'total', dir: 'desc' })
  const [expandedSig, setExpandedSig] = useState(null)
  const base = import.meta.env.DEV ? 'http://localhost:8080' : ''

  const { data: stats, isLoading: statsLoading } = useQuery({
    queryKey: ['backtestStats', days],
    queryFn: async () => {
      const res = await fetch(`${base}/api/backtest/stats?days=${days}`)
      const json = await res.json()
      return json.data || json
    },
    staleTime: 60000,
  })

  const sigParams = new URLSearchParams({ limit: '20', offset: String(sigPage * 20) })
  if (sigFilter.strategy) sigParams.set('strategy', sigFilter.strategy)
  if (sigFilter.underlying) sigParams.set('underlying', sigFilter.underlying)
  if (sigFilter.outcome) sigParams.set('outcome', sigFilter.outcome)

  const { data: signals, isLoading: sigLoading } = useQuery({
    queryKey: ['backtestSignals', sigPage, sigFilter],
    queryFn: async () => {
      const res = await fetch(`${base}/api/backtest/signals?${sigParams}`)
      const json = await res.json()
      return json.data || json
    },
    staleTime: 30000,
  })

  const fmtPnl = (v) => {
    if (v == null || isNaN(v)) return 'β€”'
    const n = Number(v)
    const color = n > 0 ? 'text-green-400' : n < 0 ? 'text-red-400' : 'text-gray-400'
    return <span className={color}>{n > 0 ? '+' : ''}{n.toFixed(2)}%</span>
  }

  const fmtWr = (v) => {
    if (v == null) return 'β€”'
    const n = Number(v)
    const color = n >= 60 ? 'text-green-400' : n >= 45 ? 'text-yellow-400' : 'text-red-400'
    return <span className={color}>{n.toFixed(1)}%</span>
  }

  const sortRows = (rows, sort) => {
    return [...rows].sort((a, b) => {
      const av = a[sort.field] ?? 0, bv = b[sort.field] ?? 0
      return sort.dir === 'asc' ? av - bv : bv - av
    })
  }

  const strategies = sortRows(stats?.strategies || [], stratSort)
  const underlyings = sortRows(stats?.underlyings || [], assetSort)
  const sigList = signals?.signals || []
  const sigTotal = signals?.total || 0

  return (
    <div className="space-y-6">
      {/* Period selector */}
      <div className="flex items-center gap-3">
        <span className="text-gray-400 text-sm">Period:</span>
        {[7, 14, 30, 90].map(d => (
          <button key={d} onClick={() => { setDays(d); setSigPage(0) }}
            className={`px-3 py-1 rounded text-sm font-medium transition-colors ${
              days === d ? 'bg-cyan-600 text-white' : 'bg-darkSurface text-gray-400 hover:text-white border border-darkBorder'
            }`}>{d}D</button>
        ))}
      </div>

      {statsLoading ? (
        <div className="flex justify-center py-12"><div className="animate-spin rounded-full h-8 w-8 border-b-2 border-cyan-500" /></div>
      ) : stats ? (
        <>
          {/* Overview cards */}
          <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
            {[
              { label: 'Total Signals', value: stats.totalSignals?.toLocaleString(), sub: `${stats.completed} completed` },
              { label: 'Win Rate', value: fmtWr(stats.overallWinRate), sub: `${stats.pending} pending` },
              { label: 'Avg PnL 24h', value: fmtPnl(stats.avgPnl24h), sub: 'option-based' },
              { label: 'Completed', value: `${stats.completed}`, sub: `${((stats.completed / (stats.totalSignals || 1)) * 100).toFixed(0)}% tracked` },
            ].map((c, i) => (
              <div key={i} className="bg-darkSurface border border-darkBorder rounded-lg p-4">
                <div className="text-xs text-gray-500 uppercase tracking-wider">{c.label}</div>
                <div className="text-xl font-bold mt-1">{c.value}</div>
                <div className="text-xs text-gray-500 mt-1">{c.sub}</div>
              </div>
            ))}
          </div>

          {/* Strategy performance table */}
          <div className="bg-darkSurface border border-darkBorder rounded-lg overflow-hidden">
            <div className="px-4 py-3 border-b border-darkBorder">
              <h3 className="font-semibold text-sm">Strategy Performance</h3>
            </div>
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="text-xs text-gray-500 uppercase border-b border-darkBorder">
                    <th className="text-left px-4 py-2">Strategy</th>
                    <SortHeader label="Signals" field="total" sort={stratSort} setSort={setStratSort} />
                    <SortHeader label="Wins" field="wins" sort={stratSort} setSort={setStratSort} />
                    <SortHeader label="Losses" field="losses" sort={stratSort} setSort={setStratSort} />
                    <SortHeader label="Win Rate" field="winRate" sort={stratSort} setSort={setStratSort} />
                    <SortHeader label="Avg 1h" field="avgPnl1h" sort={stratSort} setSort={setStratSort} />
                    <SortHeader label="Avg 4h" field="avgPnl4h" sort={stratSort} setSort={setStratSort} />
                    <SortHeader label="Avg 24h" field="avgPnl24h" sort={stratSort} setSort={setStratSort} />
                  </tr>
                </thead>
                <tbody>
                  {strategies.map((s, i) => (
                    <tr key={i} className="border-b border-darkBorder/50 hover:bg-darkBorder/30 cursor-pointer"
                        onClick={() => { setSigFilter(f => ({ ...f, strategy: f.strategy === s.strategy ? '' : s.strategy })); setSigPage(0) }}>
                      <td className="px-4 py-2 font-medium whitespace-nowrap">
                        {sigFilter.strategy === s.strategy && <span className="text-cyan-400 mr-1">●</span>}
                        {s.strategy}
                      </td>
                      <td className="text-right px-3 py-2 text-gray-400">{s.total}</td>
                      <td className="text-right px-3 py-2 text-green-400">{s.wins}</td>
                      <td className="text-right px-3 py-2 text-red-400">{s.losses}</td>
                      <td className="text-right px-3 py-2 font-medium">{fmtWr(s.winRate)}</td>
                      <td className="text-right px-3 py-2">{fmtPnl(s.avgPnl1h)}</td>
                      <td className="text-right px-3 py-2">{fmtPnl(s.avgPnl4h)}</td>
                      <td className="text-right px-3 py-2 font-medium">{fmtPnl(s.avgPnl24h)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>

          {/* Underlying performance table */}
          <div className="bg-darkSurface border border-darkBorder rounded-lg overflow-hidden">
            <div className="px-4 py-3 border-b border-darkBorder">
              <h3 className="font-semibold text-sm">Performance by Asset</h3>
            </div>
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="text-xs text-gray-500 uppercase border-b border-darkBorder">
                    <th className="text-left px-4 py-2">Asset</th>
                    <SortHeader label="Signals" field="total" sort={assetSort} setSort={setAssetSort} />
                    <SortHeader label="Wins" field="wins" sort={assetSort} setSort={setAssetSort} />
                    <SortHeader label="Win Rate" field="winRate" sort={assetSort} setSort={setAssetSort} />
                    <SortHeader label="Avg 24h PnL" field="avgPnl24h" sort={assetSort} setSort={setAssetSort} />
                  </tr>
                </thead>
                <tbody>
                  {underlyings.map((u, i) => (
                    <tr key={i} className="border-b border-darkBorder/50 hover:bg-darkBorder/30 cursor-pointer"
                        onClick={() => { setSigFilter(f => ({ ...f, underlying: f.underlying === u.underlying ? '' : u.underlying })); setSigPage(0) }}>
                      <td className="px-4 py-2 font-medium">
                        {sigFilter.underlying === u.underlying && <span className="text-cyan-400 mr-1">●</span>}
                        {u.underlying}
                      </td>
                      <td className="text-right px-3 py-2 text-gray-400">{u.total}</td>
                      <td className="text-right px-3 py-2 text-green-400">{u.wins}</td>
                      <td className="text-right px-3 py-2 font-medium">{fmtWr(u.winRate)}</td>
                      <td className="text-right px-3 py-2 font-medium">{fmtPnl(u.avgPnl24h)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
        </>
      ) : null}

      {/* Signal Log */}
      <div className="bg-darkSurface border border-darkBorder rounded-lg overflow-hidden">
        <div className="px-4 py-3 border-b border-darkBorder flex items-center justify-between flex-wrap gap-2">
          <h3 className="font-semibold text-sm">Signal Log ({sigTotal} total)</h3>
          <div className="flex gap-2">
            {['WIN', 'LOSS', 'PENDING'].map(o => (
              <button key={o} onClick={() => { setSigFilter(f => ({ ...f, outcome: f.outcome === o ? '' : o })); setSigPage(0) }}
                className={`px-2 py-0.5 rounded text-xs font-medium transition-colors ${
                  sigFilter.outcome === o
                    ? o === 'WIN' ? 'bg-green-600 text-white' : o === 'LOSS' ? 'bg-red-600 text-white' : 'bg-gray-600 text-white'
                    : 'bg-darkBorder text-gray-400 hover:text-white'
                }`}>{o}</button>
            ))}
            {(sigFilter.strategy || sigFilter.underlying || sigFilter.outcome) && (
              <button onClick={() => { setSigFilter({ strategy: '', underlying: '', outcome: '' }); setSigPage(0) }}
                className="px-2 py-0.5 rounded text-xs text-gray-500 hover:text-white">Clear</button>
            )}
          </div>
        </div>
        {sigLoading ? (
          <div className="flex justify-center py-8"><div className="animate-spin rounded-full h-6 w-6 border-b-2 border-cyan-500" /></div>
        ) : (
          <>
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="text-xs text-gray-500 uppercase border-b border-darkBorder">
                    <th className="text-left px-4 py-2">Time</th>
                    <th className="text-left px-3 py-2">Strategy</th>
                    <th className="text-left px-3 py-2">Asset</th>
                    <th className="text-center px-3 py-2">Dir</th>
                    <th className="text-right px-3 py-2">Conf</th>
                    <th className="text-right px-3 py-2">Spot</th>
                    <th className="text-right px-3 py-2">1h</th>
                    <th className="text-right px-3 py-2">4h</th>
                    <th className="text-right px-3 py-2">24h</th>
                    <th className="text-center px-3 py-2">Result</th>
                  </tr>
                </thead>
                <tbody>
                  {sigList.map((s, i) => {
                    const t = new Date(s.createdAt)
                    const dir = s.direction
                    const isExpanded = expandedSig === s.id
                    const params = s.parameters || {}
                    return (
                      <>
                        <tr key={s.id || i} className={`border-b border-darkBorder/50 hover:bg-darkBorder/30 cursor-pointer ${isExpanded ? 'bg-darkBorder/20' : ''}`}
                            onClick={() => setExpandedSig(isExpanded ? null : s.id)}>
                          <td className="px-4 py-2 text-gray-400 whitespace-nowrap text-xs">
                            <span className="text-gray-600 mr-1">{isExpanded ? 'β–Ύ' : 'β–Έ'}</span>
                            {t.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })} {t.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', hour12: false })}
                          </td>
                          <td className="px-3 py-2 whitespace-nowrap">{s.strategy}</td>
                          <td className="px-3 py-2 font-medium">{s.underlying}</td>
                          <td className="px-3 py-2 text-center">
                            {dir === 'BULLISH' ? <span className="text-green-400">β–²</span>
                             : dir === 'BEARISH' ? <span className="text-red-400">β–Ό</span>
                             : <span className="text-gray-400">β—†</span>}
                          </td>
                          <td className="text-right px-3 py-2 text-gray-400">{s.confidence}</td>
                          <td className="text-right px-3 py-2 text-gray-400">${Number(s.spotAtSignal).toLocaleString(undefined, { maximumFractionDigits: 2 })}</td>
                          <td className="text-right px-3 py-2">{fmtPnl(s.pnlPct1h)}</td>
                          <td className="text-right px-3 py-2">{fmtPnl(s.pnlPct4h)}</td>
                          <td className="text-right px-3 py-2 font-medium">{fmtPnl(s.pnlPct24h)}</td>
                          <td className="px-3 py-2 text-center">
                            {s.outcome === 'WIN' ? <span className="text-green-400 font-medium">WIN</span>
                             : s.outcome === 'LOSS' ? <span className="text-red-400 font-medium">LOSS</span>
                             : <span className="text-gray-500 text-xs">pending</span>}
                          </td>
                        </tr>
                        {isExpanded && (
                          <tr key={`${s.id}-detail`} className="bg-darkBorder/10">
                            <td colSpan={10} className="px-6 py-3">
                              <div className="text-xs space-y-2">
                                {s.description && (
                                  <p className="text-gray-300 leading-relaxed">{s.description}</p>
                                )}
                                <div className="flex flex-wrap gap-x-6 gap-y-1 text-gray-500">
                                  {s.severity && <span>Severity: <span className={
                                    s.severity === 'EXTREME' ? 'text-red-400' : s.severity === 'HIGH' ? 'text-orange-400' : 'text-gray-400'
                                  }>{s.severity}</span></span>}
                                  {s.spotAfter1h != null && <span>Spot 1h: <span className="text-gray-300">${Number(s.spotAfter1h).toLocaleString(undefined, { maximumFractionDigits: 2 })}</span></span>}
                                  {s.spotAfter4h != null && <span>Spot 4h: <span className="text-gray-300">${Number(s.spotAfter4h).toLocaleString(undefined, { maximumFractionDigits: 2 })}</span></span>}
                                  {s.spotAfter24h != null && <span>Spot 24h: <span className="text-gray-300">${Number(s.spotAfter24h).toLocaleString(undefined, { maximumFractionDigits: 2 })}</span></span>}
                                </div>
                                {Object.keys(params).length > 0 && (
                                  <div className="flex flex-wrap gap-x-4 gap-y-1 text-gray-500 pt-1 border-t border-darkBorder/50">
                                    {Object.entries(params).map(([k, v]) => (
                                      <span key={k}>{k}: <span className="text-gray-400">{typeof v === 'number' ? v.toFixed?.(4) ?? v : String(v)}</span></span>
                                    ))}
                                  </div>
                                )}
                              </div>
                            </td>
                          </tr>
                        )}
                      </>
                    )
                  })}
                  {sigList.length === 0 && (
                    <tr><td colSpan={10} className="text-center py-8 text-gray-500">No signals found</td></tr>
                  )}
                </tbody>
              </table>
            </div>
            {/* Pagination */}
            {sigTotal > 20 && (
              <div className="flex items-center justify-between px-4 py-3 border-t border-darkBorder">
                <span className="text-xs text-gray-500">
                  {sigPage * 20 + 1}–{Math.min((sigPage + 1) * 20, sigTotal)} of {sigTotal}
                </span>
                <div className="flex gap-2">
                  <button disabled={sigPage === 0} onClick={() => setSigPage(p => p - 1)}
                    className="px-3 py-1 rounded text-xs bg-darkBorder text-gray-400 hover:text-white disabled:opacity-30">Prev</button>
                  <button disabled={(sigPage + 1) * 20 >= sigTotal} onClick={() => setSigPage(p => p + 1)}
                    className="px-3 py-1 rounded text-xs bg-darkBorder text-gray-400 hover:text-white disabled:opacity-30">Next</button>
                </div>
              </div>
            )}
          </>
        )}
      </div>
    </div>
  )
}

function Dashboard() {
  const [activeTab, setActiveTab] = useState('signals') // 'signals' | 'chain' | 'whale' | 'iv-surface' | 'alerts'
  const [selectedAsset, setSelectedAsset] = useState('ALL')
  const [selectedTimeframe, setSelectedTimeframe] = useState('ALL') // New state
  const [pushStatus, setPushStatus] = useState(typeof Notification !== 'undefined' ? Notification.permission : 'default')
  const [isSubscribed, setIsSubscribed] = useState(false);
  const [isTestingPush, setIsTestingPush] = useState(false);
  const [highlightedSignal, setHighlightedSignal] = useState(null);
  const [pnlCalc, setPnlCalc] = useState({ isOpen: false, prefill: null })
  const [tradeModal, setTradeModal] = useState({ isOpen: false, signal: null })
  const [tradeResult, setTradeResult] = useState(null) // { success, data/error }

  // Fetch trading status
  const { data: tradingStatus } = useQuery({
    queryKey: ['tradingStatus'],
    queryFn: async () => {
      const base = import.meta.env.DEV ? 'http://localhost:8080' : '';
      const res = await fetch(`${base}/api/trading/status`)
      if (!res.ok) return { data: { enabled: false } }
      return res.json()
    },
    staleTime: 60000,
  })
  const tradingEnabled = tradingStatus?.data?.enabled || false

  // Open P&L calculator with prefilled data from a trade signal
  function openPnlCalc(trade) {
    if (!trade) {
      setPnlCalc({ isOpen: true, prefill: null })
      return
    }
    const tradeUnit = trade.unit || 1
    const isCombo = !!(trade.contracts && trade.contracts.length > 1)
    const rawPremium = isCombo ? (trade.totalEntry || 0) : (trade.entry || 0)
    setPnlCalc({
      isOpen: true,
      prefill: {
        type: isCombo ? 'CALL' : (trade.action?.includes('CALL') ? 'CALL' : 'PUT'),
        strike: trade.strike || trade.contracts?.[0]?.strike || 0,
        premium: trade.premiumPerUnit || (rawPremium / tradeUnit),
        qty: trade.qty || trade.contracts?.[0]?.qty || 1,
        unit: tradeUnit,
        spot: trade.spot || 0,
        isCombo,
      }
    })
  }

  // Check current subscription status on load
  useEffect(() => {
    // Force PWA to aggressively fetch the absolute latest version from the server 
    // and skip the "waiting" lifecycle phase so the Bug icon appears immediately.
    registerSW({
      immediate: true,
      onNeedRefresh() {
        // Automatically reload the page when a new version (with the Bug icon) is available
        window.location.reload(true);
      }
    });

    async function checkSub() {
      if ('serviceWorker' in navigator && 'PushManager' in window && typeof Notification !== 'undefined' && Notification.permission === 'granted') {
        const registration = await navigator.serviceWorker.ready;
        const sub = await registration.pushManager.getSubscription();
        setIsSubscribed(!!sub);
      }
    }
    checkSub();
  }, []);

  async function handleSubscribe() {
    if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
      alert('Π’Π°Ρˆ Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ ΠΈΠ»ΠΈ ОБ Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Push-увСдомлСния.');
      return;
    }
    try {
      const registration = await navigator.serviceWorker.ready;
      let permission = Notification.permission;

      if (isSubscribed) {
        const subscription = await registration.pushManager.getSubscription();
        if (subscription) {
          await subscription.unsubscribe();
          const baseUrl = import.meta.env.DEV ? 'http://localhost:8080' : '';
          await fetch(`${baseUrl}/api/notifications/unsubscribe`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(subscription)
          });
        }
        setIsSubscribed(false);
        alert('πŸ”• УвСдомлСния Π²Ρ‹ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹.');
        return;
      }

      if (permission !== 'granted') {
        permission = await Notification.requestPermission();
      }
      setPushStatus(permission);

      if (permission === 'granted') {
        const baseUrl = import.meta.env.DEV ? 'http://localhost:8080' : '';
        const vapidRes = await fetch(`${baseUrl}/api/notifications/vapidPublicKey`);
        const { publicKey } = await vapidRes.json();

        const base64ToUint8Array = base64String => {
          const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
          const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
          const rawData = window.atob(base64);
          const outputArray = new Uint8Array(rawData.length);
          for (let i = 0; i < rawData.length; ++i) {
            outputArray[i] = rawData.charCodeAt(i);
          }
          return outputArray;
        };

        const subscription = await registration.pushManager.subscribe({
          userVisibleOnly: true,
          applicationServerKey: base64ToUint8Array(publicKey)
        });

        await fetch(`${baseUrl}/api/notifications/subscribe`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(subscription)
        });

        setIsSubscribed(true);
        alert('βœ… УвСдомлСния ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Ρ‹!');
      }
    } catch (error) {
      console.error('Push Subscription Error:', error);
      alert('Ошибка подписки Π½Π° Push-увСдомлСния. Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ увСдомлСния для этого сайта.');
    }
  }

  async function handleTestNotification() {
    if (isTestingPush) return;
    setIsTestingPush(true);
    try {
      const baseUrl = import.meta.env.DEV ? 'http://localhost:8080' : '';
      const res = await fetch(`${baseUrl}/api/notifications/test`, { method: 'POST' });
      if (!res.ok) {
        const data = await res.json();
        throw new Error(data.error || 'Failed to send test push');
      }
    } catch (e) {
      console.error('Ошибка ΠΏΡ€ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ΅ тСстового ΠΏΡƒΡˆΠ°:', e);
      alert('Ошибка ΠΏΡ€ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ΅ тСстового ΠΏΡƒΡˆΠ°: ' + e.message);
    } finally {
      // Disable the button for 5 seconds to prevent spamming Chrome's push heuristic
      setTimeout(() => setIsTestingPush(false), 5000);
    }
  }

  const { data, isLoading, error } = useQuery({
    queryKey: ['dashboardData', selectedTimeframe],
    queryFn: async () => {
      // Determine the API base URL based on the environment
      const baseUrl = import.meta.env.DEV ? 'http://localhost:8080' : '';
      const res = await fetch(`${baseUrl}/api/dashboard?timeframe=${selectedTimeframe}`)
      if (!res.ok) throw new Error('Failed to fetch data')
      return res.json()
    }
  })

  // Deep Link Highlighting Logic
  useEffect(() => {
    if (data?.signals && data.signals.length > 0) {
      const params = new URLSearchParams(window.location.search);
      const targetId = params.get('signalId');

      if (targetId) {
        // Switch to signals tab and show ALL assets so the card is visible
        setActiveTab('signals');
        setSelectedAsset('ALL');
        setHighlightedSignal(targetId);

        // Allow React a tick to render the 'ALL' list if it was previously filtered
        setTimeout(() => {
          const el = document.getElementById(targetId);
          if (el) {
            el.scrollIntoView({ behavior: 'smooth', block: 'center' });
          }
          // Remove URL param cleanly without reloading the page
          window.history.replaceState({}, document.title, window.location.pathname);
        }, 150);

        // Turn off the glowing effect after 3.5 seconds
        setTimeout(() => {
          setHighlightedSignal(null);
        }, 3500);
      }
    }
  }, [data?.signals]);

  const assets = ['ALL', 'BTC', 'ETH', 'SOL', 'BNB', 'XRP', 'DOGE']
  const timeframes = ['ALL', '1W', '2W', '1M']

  function renderIcon(type, direction) {
    if (type === 'COMBO') {
      if (direction === 'NEUTRAL' || direction === 'NEUTRAL_VOLATILE') return <AlignVerticalJustifyCenter className="text-volatilityText" size={20} />
      if (direction === 'NEUTRAL_RANGE') return <Activity className="text-gray-400" size={20} />
      return <Activity className="text-blue-500" size={20} />
    }
    if (type === 'ANOMALY') return <ShieldAlert className="text-red-500" size={20} />
    if (direction === 'BULLISH') return <TrendingUp className="text-bullishText" size={20} />
    if (direction === 'BEARISH') return <TrendingDown className="text-bearishText" size={20} />
    return <Activity size={20} />
  }

  function renderColor(type, direction) {
    if (type === 'COMBO') return 'border-volatilityText bg-volatilityBg'
    if (type === 'ANOMALY') return 'border-red-500 bg-red-500/10'
    if (direction === 'BULLISH') return 'border-bullishText bg-bullishBg'
    if (direction === 'BEARISH') return 'border-bearishText bg-bearishBg'
    return 'border-darkBorder bg-darkSurface'
  }

  const signals = data?.signals || []
  const filteredSignals = selectedAsset === 'ALL'
    ? signals
    : signals.filter(s => s.underlying === selectedAsset)

  return (
    <div className="min-h-screen bg-darkBg text-gray-200 p-6 font-sans overflow-x-hidden">

      {/* HEADER SECTION */}
      <header className="flex flex-col xl:flex-row justify-between items-start xl:items-center gap-4 mb-8 border-b border-darkBorder pb-4 w-full">
        <div>
          <h1 className="text-3xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-blue-400 to-purple-500">
            Options Screener V2
          </h1>
          <p className="text-sm text-gray-400 mt-1">
            Advanced Auto-Trading Signals & Flow
          </p>
        </div>

        <div className="flex flex-col xl:items-end gap-3 w-full xl:w-auto mt-2 xl:mt-0">
          <div className="flex gap-2 w-full justify-start xl:justify-end items-center flex-wrap">
            <button
              onClick={handleSubscribe}
              className={`p-2 rounded-lg border flex-shrink-0 flex items-center justify-center transition-colors shadow-sm ${isSubscribed
                ? 'bg-emerald-500/10 border-emerald-500/50 text-emerald-400 hover:bg-emerald-500/20'
                : 'bg-darkSurface border-darkBorder text-gray-400 hover:text-white hover:border-gray-500'
                }`}
              title={isSubscribed ? "Π’Ρ‹ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ увСдомлСния" : "Π’ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ увСдомлСния"}
            >
              {isSubscribed ? <BellRing size={18} /> : <BellOff size={18} />}
            </button>
            {/* Active Asset Filter */}
            <div className="flex gap-2 bg-darkSurface p-1 rounded-lg border border-darkBorder flex-wrap">
              {assets.map(a => (
                <button
                  key={`asset-${a}`}
                  onClick={() => setSelectedAsset(a)}
                  className={`px-4 py-1.5 rounded-md text-sm font-medium transition-colors whitespace-nowrap ${selectedAsset === a
                    ? 'bg-blue-600 text-white'
                    : 'text-gray-400 hover:text-white hover:bg-darkBorder'
                    }`}
                >
                  {a}
                </button>
              ))}
            </div>
          </div>

          {/* Expiry Timeframe Filter */}
          <div className="flex gap-2 bg-darkSurface p-1 rounded-lg border border-darkBorder w-full xl:w-auto justify-start flex-wrap">
            <span className="text-sm text-gray-500 flex items-center px-2">Expiry:</span>
            {timeframes.map(tf => (
              <button
                key={`tf-${tf}`}
                onClick={() => setSelectedTimeframe(tf)}
                className={`px-3 py-1 rounded-md text-xs font-bold transition-colors ${selectedTimeframe === tf
                  ? 'bg-purple-600 outline outline-1 outline-purple-400 text-white'
                  : 'text-gray-400 hover:text-white hover:bg-darkBorder'
                  }`}
              >
                {tf}
              </button>
            ))}
          </div>
        </div>
      </header>

      {/* TAB NAVIGATION */}
      <div className="flex gap-1 mb-6 bg-darkSurface p-1 rounded-lg border border-darkBorder w-fit">
        <button onClick={() => setActiveTab('signals')}
          className={`flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-colors ${
            activeTab === 'signals' ? 'bg-blue-600 text-white' : 'text-gray-400 hover:text-white hover:bg-darkBorder'
          }`}>
          <BarChart3 size={16} /> Signals
        </button>
        <button onClick={() => setActiveTab('chain')}
          className={`flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-colors ${
            activeTab === 'chain' ? 'bg-blue-600 text-white' : 'text-gray-400 hover:text-white hover:bg-darkBorder'
          }`}>
          <Table2 size={16} /> Options Chain
        </button>
        <button onClick={() => setActiveTab('whale')}
          className={`flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-colors ${
            activeTab === 'whale' ? 'bg-amber-600 text-white' : 'text-gray-400 hover:text-white hover:bg-darkBorder'
          }`}>
          πŸ‹ Whale Flow
        </button>
        <button onClick={() => setActiveTab('iv-surface')}
          className={`flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-colors ${
            activeTab === 'iv-surface' ? 'bg-purple-600 text-white' : 'text-gray-400 hover:text-white hover:bg-darkBorder'
          }`}>
          <TrendingUp size={16} /> IV Surface
        </button>
        <button onClick={() => setActiveTab('alerts')}
          className={`flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-colors ${
            activeTab === 'alerts' ? 'bg-green-600 text-white' : 'text-gray-400 hover:text-white hover:bg-darkBorder'
          }`}>
          <Bell size={16} /> Alerts
        </button>
        <button onClick={() => setActiveTab('backtest')}
          className={`flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-colors ${
            activeTab === 'backtest' ? 'bg-cyan-600 text-white' : 'text-gray-400 hover:text-white hover:bg-darkBorder'
          }`}>
          πŸ“Š Backtest
        </button>
        {tradingEnabled && (
          <button onClick={() => setActiveTab('trading')}
            className={`flex items-center gap-2 px-4 py-2 rounded-md text-sm font-medium transition-colors ${
              activeTab === 'trading' ? 'bg-orange-600 text-white' : 'text-gray-400 hover:text-white hover:bg-darkBorder'
            }`}>
            ⚑ Trading
          </button>
        )}
      </div>

      {/* CHAIN VIEW TAB */}
      {activeTab === 'chain' && <ChainView />}

      {/* WHALE FLOW TAB */}
      {activeTab === 'whale' && <WhaleFlow />}

      {/* IV SURFACE TAB */}
      {activeTab === 'iv-surface' && <IvSurface />}

      {/* CUSTOM ALERTS TAB */}
      {activeTab === 'alerts' && <CustomAlerts />}

      {/* BACKTEST TAB */}
      {activeTab === 'backtest' && <BacktestTab />}

      {/* TRADING TAB β€” Positions + Orders + Account */}
      {activeTab === 'trading' && <TradingTab />}

      {/* SIGNALS TAB */}
      {activeTab === 'signals' && <>

      {/* ERROR / LOADING STATE */}
      {isLoading && (
        <div className="flex justify-center items-center h-64">
          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500"></div>
        </div>
      )}

      {error && (
        <div className="bg-red-500/10 border border-red-500 text-red-400 p-4 rounded-lg flex items-center gap-3">
          <AlertTriangle />
          <div>
            <p className="font-bold">Error connecting to server</p>
            <p className="text-sm text-red-300">Please try again later or check your connection.</p>
          </div>
        </div>
      )}

      {/* SIGNALS GRID */}
      {!isLoading && !error && (
        <div>
          <div className="flex justify-between items-end mb-4">
            <h2 className="text-xl font-semibold flex items-center gap-2">
              <Activity className="text-blue-500" /> Actionable Signals
            </h2>
            <div className="text-sm text-gray-500">
              Showing {filteredSignals.length} high-confidence setups
            </div>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
            {filteredSignals.length === 0 ? (
              <div className="col-span-full py-12 text-center text-gray-500 bg-darkSurface rounded-xl border border-darkBorder">
                No active high-confidence signals for {selectedAsset}. Market is quiet.
              </div>
            ) : (
              filteredSignals.map(sig => {
              const sigCardClasses = `flex flex-col rounded-xl border p-4 shadow-lg transition-all duration-500 hover:-translate-y-1 bg-darkSurface border-l-4 ${renderColor(sig.type, sig.direction)} ${highlightedSignal === sig.id
                    ? 'ring-4 ring-emerald-500 shadow-[0_0_20px_rgba(16,185,129,0.3)] border-emerald-500 scale-[1.02]'
                    : 'border-t-darkBorder border-r-darkBorder border-b-darkBorder'
                    }`
              return (
                <div
                  key={sig.id}
                  id={sig.id}
                  className={sigCardClasses}
                >
                  <div className="flex justify-between items-start mb-3">
                    <div className="flex items-center gap-2">
                      <div className={`p-1.5 rounded-md border ${
                        sig.signal === 'BUY_CALL' ? 'bg-green-600/20 border-green-500/40' :
                        sig.signal === 'BUY_PUT' ? 'bg-red-600/20 border-red-500/40' :
                        sig.strategy === 'Gamma Play' ? 'bg-purple-600/20 border-purple-500/40' :
                        sig.strategy === 'Unusual Volume' ? 'bg-amber-600/20 border-amber-500/40' :
                        (sig.strategy?.includes('Straddle') || sig.strategy?.includes('Strangle') || sig.strategy?.includes('Weekend')) ? 'bg-blue-600/20 border-blue-500/40' :
                        'bg-darkBg border-darkBorder'
                      }`}>
                        {renderIcon(sig.type, sig.direction)}
                      </div>
                      <div>
                        <span className="text-xs font-bold text-gray-400 tracking-wider">
                          {sig.underlying}
                        </span>
                        <h3 className={`text-lg font-bold leading-tight mt-0.5 ${
                          sig.signal === 'BUY_CALL' ? 'text-green-400' :
                          sig.signal === 'BUY_PUT' ? 'text-red-400' :
                          sig.strategy === 'Gamma Play' ? 'text-purple-400' :
                          sig.strategy === 'Unusual Volume' ? 'text-amber-400' :
                          (sig.strategy?.includes('Straddle') || sig.strategy?.includes('Strangle') || sig.strategy?.includes('Weekend')) ? 'text-blue-400' :
                          'text-white'
                        }`}>
                          {sig.strategy}
                        </h3>
                      </div>
                    </div>

                    {/* Confidence Badge */}
                    <div className={`px-2 py-0.5 rounded text-xs font-bold ${sig.confidence > 80 ? 'bg-green-500/20 text-green-400' :
                      sig.confidence > 60 ? 'bg-yellow-500/20 text-yellow-400' :
                        'bg-gray-500/20 text-gray-400'
                      }`}>
                      {sig.confidence}%
                    </div>
                  </div>

                  <div className="text-sm text-gray-300 mb-4 flex-grow">
                    {sig.rationale}
                  </div>

                  {/* Tooltip / Helper text */}
                  {sig.tooltip && (
                    <div className="mt-auto pt-3 border-t border-darkBorder/50 flex items-start gap-2 text-xs text-gray-400">
                      <Info size={14} className="mt-0.5 flex-shrink-0 text-blue-400" />
                      <p className="whitespace-pre-line">{sig.tooltip}</p>
                    </div>
                  )}

                  {/* Explicit Legs Selection */}
                  {sig.legs && sig.legs.length > 0 && (
                    <div className="mt-3 flex flex-col gap-1 text-xs font-mono bg-darkBg p-2 rounded-md border border-darkBorder text-gray-300">
                      {sig.legs.map((leg, i) => (
                        <div key={i} className={`py-0.5 ${leg.startsWith('BUY') ? 'text-blue-400' : 'text-red-400'}`}>
                          {leg}
                        </div>
                      ))}
                    </div>
                  )}

                  {/* Trade Recommendation Card */}
                  {sig.trade && (
                    <div className="mt-3 text-xs font-mono bg-darkBg rounded-md border border-darkBorder overflow-hidden">
                      {/* Header */}
                      <div className={`flex justify-between items-center px-3 py-1.5 border-b border-darkBorder ${
                        sig.signal === 'BUY_CALL' ? 'bg-green-600/20' :
                        sig.signal === 'BUY_PUT' ? 'bg-red-600/20' :
                        sig.strategy === 'Gamma Play' ? 'bg-purple-600/20' :
                        sig.strategy === 'Unusual Volume' ? 'bg-amber-600/20' :
                        'bg-blue-600/20'
                      }`}>
                        <span className={`font-bold text-[11px] ${
                          sig.signal === 'BUY_CALL' ? 'text-green-400' :
                          sig.signal === 'BUY_PUT' ? 'text-red-400' :
                          sig.strategy === 'Gamma Play' ? 'text-purple-400' :
                          sig.strategy === 'Unusual Volume' ? 'text-amber-400' :
                          'text-blue-400'
                        }`}>{sig.trade.action || sig.strategy}</span>
                        <span className={`px-1.5 py-0.5 rounded text-[10px] font-bold ${
                          sig.trade.timeDecayRisk === 'CRITICAL' ? 'bg-red-500/20 text-red-400' :
                          sig.trade.timeDecayRisk === 'HIGH' ? 'bg-orange-500/20 text-orange-400' :
                          sig.trade.timeDecayRisk === 'MEDIUM' ? 'bg-yellow-500/20 text-yellow-400' :
                          'bg-green-500/20 text-green-400'
                        }`}>
                          ⏳ {sig.trade.dte}d ({sig.trade.timeDecayRisk})
                        </span>
                      </div>

                      <div className="px-3 py-2 space-y-1.5">
                        {/* Contract & Entry */}
                        {sig.trade.contract && (
                          <>
                            <div className="flex justify-between">
                              <span className="text-gray-500">ΠšΠΎΠ½Ρ‚Ρ€Π°ΠΊΡ‚:</span>
                              <span className="text-blue-400 font-bold">{sig.trade.contract}</span>
                            </div>
                            <div className="flex justify-between">
                              <span className="text-gray-500">Π‘Ρ‚Ρ€Π°ΠΉΠΊ:</span>
                              <span className="text-white">${sig.trade.strike?.toLocaleString()}</span>
                            </div>
                            <div className="flex justify-between">
                              <span className="text-gray-500">Spot сСйчас:</span>
                              <span className="text-white">${sig.trade.spot?.toLocaleString()}</span>
                            </div>
                          </>
                        )}

                        {/* Combo contracts */}
                        {sig.trade.contracts && sig.trade.contracts.map((c, i) => (
                          <div key={i} className="flex justify-between">
                            <span className="text-gray-500">{c.type} {c.qty > 1 ? `Γ—${c.qty}` : ''}:</span>
                            <span className="text-blue-400 font-bold text-[10px]">{c.symbol} @ ${c.entry}</span>
                          </div>
                        ))}

                        {/* Entry */}
                        <div className="flex justify-between items-center border-t border-darkBorder/50 pt-1.5 mt-1">
                          <span className="text-gray-400 font-bold">πŸ’° ΠŸΡ€Π΅ΠΌΠΈΡƒΠΌ:</span>
                          <span className="text-white font-bold">
                            ${sig.trade.entry?.toFixed(4) || sig.trade.totalEntry?.toFixed(4)}/ct
                            {sig.trade.unit > 1 && <span className="text-gray-500 text-[10px] ml-1">(${sig.trade.premiumPerUnit?.toFixed(4)}/unit, 1ct={sig.trade.unit})</span>}
                          </span>
                        </div>

                        {/* Breakeven */}
                        {sig.trade.breakeven && (
                          <div className="flex justify-between">
                            <span className="text-gray-500">πŸ“ Π‘Π΅Π·ΡƒΠ±Ρ‹Ρ‚ΠΎΠΊ:</span>
                            <span className="text-yellow-400">Spot @ ${sig.trade.breakeven?.toLocaleString()}</span>
                          </div>
                        )}
                        {sig.trade.breakevenUp && (
                          <div className="flex justify-between">
                            <span className="text-gray-500">πŸ“ Π‘Π΅Π·ΡƒΠ±Ρ‹Ρ‚ΠΎΠΊ:</span>
                            <span className="text-yellow-400 text-[10px]">↑${sig.trade.breakevenUp?.toLocaleString()} / ↓${sig.trade.breakevenDown?.toLocaleString()}</span>
                          </div>
                        )}

                        {/* Target */}
                        {sig.trade.target && (
                          <div className="flex justify-between items-center bg-green-500/10 border border-green-500/20 px-1.5 py-1 rounded">
                            <span className="text-green-500/80 font-bold">🎯 ВСйк (+{sig.trade.target.returnPct}%):</span>
                            {sig.trade.target.spotPrice && (
                              <span className="text-green-400 font-bold">Spot @ ${sig.trade.target.spotPrice?.toLocaleString()}</span>
                            )}
                            {sig.trade.target.spotUp && (
                              <span className="text-green-400 font-bold text-[10px]">↑${sig.trade.target.spotUp?.toLocaleString()} / ↓${sig.trade.target.spotDown?.toLocaleString()}</span>
                            )}
                          </div>
                        )}

                        {/* Stop Loss β€” only show if concrete spotPrice exists (not "premium=max loss" note) */}
                        {sig.trade.stopLoss?.spotPrice && (
                          <div className="flex justify-between items-center bg-red-500/10 border border-red-500/20 px-1.5 py-1 rounded">
                            <span className="text-red-500/80 font-bold">πŸ›‘ Π‘Ρ‚ΠΎΠΏ (-{sig.trade.stopLoss.lossPct}%):</span>
                            <span className="text-red-400 font-bold">Spot @ ${sig.trade.stopLoss.spotPrice?.toLocaleString()}</span>
                          </div>
                        )}

                        {/* Whale Info (Unusual Volume) */}
                        {sig.trade.whaleInfo && (
                          <div className="flex justify-between items-center bg-amber-500/10 border border-amber-500/20 px-1.5 py-1 rounded">
                            <span className="text-amber-500/80 font-bold">πŸ‹ ΠšΠΈΡ‚ Π²Π»ΠΈΠ»:</span>
                            <span className="text-amber-400 font-bold">${Number(sig.trade.whaleInfo.totalPremium).toLocaleString('en-US', { maximumFractionDigits: 0 })} ({sig.trade.whaleInfo.voiRatio}x V/OI)</span>
                          </div>
                        )}

                        {/* Gamma Info */}
                        {sig.trade.gammaInfo && (
                          <div className="flex justify-between items-center bg-purple-500/10 border border-purple-500/20 px-1.5 py-1 rounded">
                            <span className="text-purple-400/80 font-bold">⚑ Gamma:</span>
                            <span className="text-purple-400 font-bold">1% spot β†’ {sig.trade.gammaInfo.premiumMoveFor1PctSpot?.toFixed(0)}% ΠΏΡ€Π΅ΠΌΠΈΡƒΠΌ ({sig.trade.gammaInfo.moneyness})</span>
                          </div>
                        )}

                        {/* Spot move needed for target (gamma plays) */}
                        {sig.trade.target?.spotMovePct && (
                          <div className="flex justify-between text-[10px]">
                            <span className="text-gray-500">Spot Π½ΡƒΠΆΠ½ΠΎ ΠΏΡ€ΠΎΠΉΡ‚ΠΈ:</span>
                            <span className="text-purple-400 font-bold">{sig.trade.target.spotMovePct}%</span>
                          </div>
                        )}

                        {/* Max Loss & Risk/Reward */}
                        <div className="flex justify-between items-center border-t border-darkBorder/50 pt-1.5 mt-1">
                          <span className="text-gray-500">Макс. ΡƒΠ±Ρ‹Ρ‚ΠΎΠΊ:</span>
                          <span className="text-red-400">${sig.trade.maxLoss?.toFixed(4)}</span>
                        </div>
                        <div className="flex justify-between items-center">
                          <span className="text-gray-500">Risk/Reward:</span>
                          <div className="flex items-center gap-2">
                            <span className="text-green-400">{sig.trade.riskReward}</span>
                            <button onClick={() => openPnlCalc(sig.trade)}
                              className="px-1.5 py-0.5 bg-blue-600/20 border border-blue-500/30 rounded text-blue-400 text-[10px] font-bold hover:bg-blue-600/40 transition-colors">
                              πŸ“Š Calc
                            </button>
                            {tradingEnabled && (sig.trade.symbol || sig.trade.contract || sig.trade.contracts?.[0]?.symbol) && (
                              <button onClick={() => setTradeModal({ isOpen: true, signal: sig })}
                                className="px-1.5 py-0.5 bg-green-600/20 border border-green-500/30 rounded text-green-400 text-[10px] font-bold hover:bg-green-600/40 transition-colors">
                                ⚑ Execute
                              </button>
                            )}
                          </div>
                        </div>

                        {/* Greeks footer */}
                        <div className="flex justify-start gap-3 items-center mt-1 pt-1.5 border-t border-darkBorder/30">
                          {sig.trade.delta && <span className="text-gray-500 text-[10px]">Ξ” <span className="text-gray-300">{sig.trade.delta}</span></span>}
                          {sig.trade.gamma && <span className="text-gray-500 text-[10px]">Ξ“ <span className="text-gray-300">{Number(sig.trade.gamma).toFixed(5)}</span></span>}
                          {sig.trade.theta && <span className="text-gray-500 text-[10px]">Θ <span className="text-gray-300">{Number(sig.trade.theta).toFixed(4)}</span></span>}
                          {sig.trade.dte && <span className="text-gray-500 text-[10px]">DTE <span className="text-gray-300">{sig.trade.dte}d</span></span>}
                          {sig.trade.qty && sig.trade.qty > 1 && <span className="text-gray-500 text-[10px]">QTY <span className="text-gray-300">{sig.trade.qty}</span></span>}
                        </div>
                      </div>
                    </div>
                  )}

                  {/* Legacy Metrics (for non-strategy signals like Unusual Volume, Gamma Play) */}
                  {!sig.trade && sig.parameters && (
                    <div className="mt-3 grid grid-cols-2 gap-2 text-xs font-mono bg-darkBg px-2 py-2 rounded-md border border-darkBorder text-gray-400">
                      {sig.parameters.symbol && <div className="col-span-2 flex justify-between"><span className="text-gray-500">Contract:</span> <span className="text-blue-400 font-bold">{sig.parameters.symbol}</span></div>}
                      {sig.parameters.spot && <div className="col-span-2 flex justify-between"><span className="text-gray-500">Spot:</span> <span className="text-white">${parseFloat(sig.parameters.spot).toLocaleString()}</span></div>}

                      {sig.parameters.costUsd !== undefined && (
                        <div className="col-span-2 flex justify-between items-center border-t border-darkBorder border-dashed pt-1 mt-1">
                          <span className="text-gray-400">ΠŸΡ€Π΅ΠΌΠΈΡƒΠΌ (ΠšΠΎΠ½Ρ‚Ρ€Π°ΠΊΡ‚):</span>
                          <span className="font-bold text-white">${Number(sig.parameters.costUsd).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 4 })}</span>
                        </div>
                      )}

                      {sig.parameters.totalWhalePremium !== undefined && (
                        <div className="col-span-2 flex justify-between items-center mt-1 pt-1 bg-amber-500/10 border border-amber-500/20 px-1.5 py-0.5 rounded">
                          <span className="text-amber-500/80 font-bold text-[11px]">πŸ’° Whale Volume (Total):</span>
                          <span className="font-bold text-amber-400 text-[11px]">${Number(sig.parameters.totalWhalePremium).toLocaleString('en-US', { maximumFractionDigits: 0 })}</span>
                        </div>
                      )}

                      {(sig.parameters.ivRank || sig.parameters.delta || sig.parameters.dte) && (
                        <div className="col-span-2 flex justify-start gap-4 items-center mt-2 pt-2 border-t border-darkBorder/30">
                          {sig.parameters.ivRank && <span className="text-gray-500 text-[10px] uppercase">IV Rank: <span className="text-gray-300 font-mono">{sig.parameters.ivRank}</span></span>}
                          {sig.parameters.delta && <span className="text-gray-500 text-[10px] uppercase">Delta: <span className="text-gray-300 font-mono">{sig.parameters.delta}</span></span>}
                          {sig.parameters.dte && <span className="text-gray-500 text-[10px] uppercase">DTE: <span className="text-gray-300 font-mono">{sig.parameters.dte}d</span></span>}
                        </div>
                      )}
                    </div>
                  )}

                </div>
              )})
            )}
          </div>
        </div>
      )}

      </>}

      {/* Trade Execution Modal */}
      {tradeModal.isOpen && tradeModal.signal && (
        <TradeModal signal={tradeModal.signal} tradeResult={tradeResult} setTradeResult={setTradeResult}
          onClose={() => { setTradeModal({ isOpen: false, signal: null }); setTradeResult(null) }} />
      )}

      {/* P&L Calculator Modal */}
      <PnLCalculator isOpen={pnlCalc.isOpen} onClose={() => setPnlCalc({ isOpen: false, prefill: null })} prefill={pnlCalc.prefill} />

      {/* Floating Calc Button */}
      <button onClick={() => openPnlCalc(null)}
        className="fixed bottom-6 right-6 bg-blue-600 hover:bg-blue-700 text-white rounded-full w-12 h-12 flex items-center justify-center shadow-lg transition-all hover:scale-110 z-40"
        title="P&L Calculator">
        πŸ“Š
      </button>
    </div>
  )
}

export default App

πŸ“œ Git History

e841599feat: expired options tracking + exercise history + exit reason fix3 months ago
c004349ui: color-coded strategy cards + cleanup signal display3 months ago
d974f99fix: P&L Calculator uses per-unit premium for correct breakeven/payoff3 months ago
9740e5dfeat: combo TP per leg, position sizing from Binance balance, 2-leg TradeModal3 months ago
1f928d1fix: signal dedup was broken β€” 5615 duplicates cleaned, sortable backtest tables3 months ago
33f4e0efeat: backtest tab β€” strategy/asset tables, signal log with filters3 months ago
43817b9feat: trading stats + trade journal β€” Binance sync, stats bar, journal table3 months ago
612398cfeat: signal reliability overhaul β€” OI data, liquidity gate, realistic PnL tracking3 months ago
3320c3afix: Trading tab β€” balance shows marginBalance, PnL reads unrealizedPNL3 months ago
7bd5a13feat: auto-TP trade manager + $5 position cap3 months ago
Show last diff
Loading...