'use client'

/**
 * Open positions panel — what's currently on the book.
 *
 * The single most-asked question on any trading dashboard: "what do I hold
 * right now?" Polls /api/positions/open + /api/positions/today every 15s.
 * Compact enough to embed at the top of Dashboard AND Trades.
 *
 * Empty state is intentional: explicitly says "0 open" rather than hiding,
 * so the user can confirm the bot isn't doing anything weird off-screen.
 */

import { useEffect, useState } from 'react'
import { useLocale } from 'next-intl'
import { useAccount, useSignMessage } from 'wagmi'
import {
  getOpenPositions,
  getTodayStats,
  manualCloseTrade,
  setTradeGrow,
  type OpenPosition,
  type TodayStats,
} from '@/lib/api'
import { getCachedViewEnvelope, signRequest } from '@/lib/signedRequest'
import { isUserRejection, walletErrorLabel } from '@/lib/walletError'

const POLL_MS = 15_000

function fmtMoney(n: number | null | undefined, opts: { sign?: boolean } = {}) {
  if (n == null || isNaN(n)) return '—'
  const sign = opts.sign === true
  const abs = Math.abs(n).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
  if (n < 0) return '-$' + abs
  if (sign && n > 0) return '+$' + abs
  return '$' + abs
}
function fmtPct(n: number | null | undefined) {
  if (n == null || isNaN(n)) return '—'
  return (n >= 0 ? '+' : '') + n.toFixed(2) + '%'
}
function fmtHold(min: number) {
  if (min < 60) return `${min}m`
  const h = Math.floor(min / 60), m = min % 60
  if (h < 24) return `${h}h ${m}m`
  return `${Math.floor(h / 24)}d ${h % 24}h`
}

function PositionRow({ p, onClose, onToggleGrow, growBusy, isZh }: {
  p: OpenPosition
  onClose: (p: OpenPosition) => void
  onToggleGrow: (p: OpenPosition) => void
  growBusy: boolean
  isZh: boolean
}) {
  const pnlTone = (p.unrealized_pct ?? 0) > 0 ? 'up'
                : (p.unrealized_pct ?? 0) < 0 ? 'down' : 'idle'
  const pnlColor = pnlTone === 'up' ? 'var(--up)' : pnlTone === 'down' ? 'var(--down)' : 'var(--ink-3)'

  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: '70px 60px 1fr 1fr 80px 1fr 90px',
      gap: 12, alignItems: 'center',
      padding: '10px 14px',
      borderTop: '1px solid var(--line)',
      fontSize: 13,
    }}>
      {/* Asset + paper tag */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
        <span className={`asset-dot ${p.asset.toLowerCase()}`} />
        <span style={{ fontWeight: 600 }}>{p.asset}</span>
        {p.is_paper && (
          <span style={{
            fontSize: 9, padding: '1px 5px', borderRadius: 3,
            background: 'rgba(245,158,11,0.15)', color: '#f59e0b',
          }}>P</span>
        )}
      </div>
      {/* Side */}
      <span className={`side-pill ${p.side}`}>
        {p.side === 'long'
          ? '↗ LONG'
          : '↘ SHORT'}
      </span>
      {/* Entry → Current */}
      <div className="mono" style={{ fontSize: 12 }}>
        <div style={{ color: 'var(--ink-3)', fontSize: 10 }}>entry → mark</div>
        <div>
          {fmtMoney(p.entry_price)}
          <span style={{ color: 'var(--ink-4)' }}> → </span>
          {p.current_price != null ? fmtMoney(p.current_price) : <span style={{ color: 'var(--ink-4)' }}>n/a</span>}
        </div>
      </div>
      {/* Size + leverage (size = OPEN notional after de-risk) */}
      <div className="mono" style={{ fontSize: 12 }}>
        <div style={{ color: 'var(--ink-3)', fontSize: 10 }}>open size · lev</div>
        <div>
          {p.size_usd != null ? '$' + p.size_usd.toFixed(0) : '—'}
          {p.leverage != null && <span style={{ color: 'var(--ink-4)' }}> · {p.leverage}×</span>}
        </div>
        {((p.derisk_steps ?? 0) > 0 || (p.addon_steps ?? 0) > 0) && (
          <div style={{ fontSize: 9, marginTop: 2 }}>
            {(p.addon_steps ?? 0) > 0 && (
              <span style={{ color: 'var(--up)' }}>{`⬆ pyramided ×${p.addon_steps} `}</span>
            )}
            {(p.derisk_steps ?? 0) > 0 && (
              <span style={{ color: 'var(--down)' }}>{`⬇ de-risked ×${p.derisk_steps}`}</span>
            )}
          </div>
        )}
        {/* Per-trade Grow (pyramiding) switch */}
        <button
          onClick={() => onToggleGrow(p)}
          disabled={growBusy}
          title={p.grow_mode
            ? (isZh ? 'Grow 已开启：趋势确认后会继续顺势加仓。点击关闭。' : 'Grow ON — scales INTO this winner on confirmed trend. Click to turn off.')
            : (isZh ? 'Grow 已关闭：仅持有并做保护性降风险。点击后允许顺势加仓。' : 'Grow OFF — hold + protective de-risk only. Click to let it pyramid.')}
          style={{
            marginTop: 4, fontSize: 9, fontWeight: 700, padding: '2px 7px',
            borderRadius: 999, cursor: growBusy ? 'wait' : 'pointer',
            border: '1px solid var(--line)',
            background: p.grow_mode ? 'var(--up, #16a34a)' : 'transparent',
            color: p.grow_mode ? '#fff' : 'var(--ink-3)',
          }}
        >
          {p.grow_mode ? '⬆ Grow ON' : 'Grow OFF'}
        </button>
      </div>
      {/* Hold time */}
      <div className="mono" style={{ fontSize: 12, color: 'var(--ink-2)' }}>
        {fmtHold(p.hold_minutes)}
      </div>
      {/* Unrealized PnL */}
      <div style={{ textAlign: 'right' }}>
        <div style={{ fontSize: 14, fontWeight: 600, color: pnlColor, fontVariantNumeric: 'tabular-nums' }}>
          {fmtMoney(p.unrealized_usd, { sign: true })}
        </div>
        <div style={{ fontSize: 11, color: pnlColor, opacity: 0.85 }}>
          {fmtPct(p.unrealized_pct)}
        </div>
        {p.realized_usd != null && p.realized_usd !== 0 && (
          <div style={{ fontSize: 10, color: 'var(--ink-3)', marginTop: 1 }}>
            locked in {fmtMoney(p.realized_usd, { sign: true })}
          </div>
        )}
      </div>
      {/* Emergency close — bypasses TP/SL/schedule. Always available. */}
      <button
        onClick={() => onClose(p)}
        className="btn ghost"
        style={{
          padding: '6px 10px', fontSize: 11, fontWeight: 600,
          color: 'var(--down)',
          border: '1px solid color-mix(in oklab, var(--down) 25%, var(--line))',
        }}
        title={isZh ? '立即平掉这个仓位' : 'Close this position immediately'}
      >
        {isZh ? '立即平仓' : 'Close now'}
      </button>
    </div>
  )
}

export default function OpenPositions() {
  const locale = useLocale()
  const isZh = false  // i18n shelved — Chinese branches kept as dead code for future revival; see messages/zh.json
  const { address, isConnected } = useAccount()
  const { signMessageAsync } = useSignMessage()
  const [mounted, setMounted] = useState(false)
  const [positions, setPositions] = useState<OpenPosition[] | null>(null)
  const [today, setToday] = useState<TodayStats | null>(null)
  const [err, setErr] = useState<string | null>(null)
  const [needsUnlock, setNeedsUnlock] = useState(false)
  // Close-confirmation modal state
  const [closing, setClosing] = useState<OpenPosition | null>(null)
  const [closeState, setCloseState] = useState<'idle'|'signing'|'closing'|'err'>('idle')

  useEffect(() => { setMounted(true) }, [])
  const [closeErr, setCloseErr] = useState('')
  const [growId, setGrowId] = useState<number | null>(null)

  async function toggleGrow(p: OpenPosition) {
    if (!address || growId !== null) return
    const next = !p.grow_mode
    setGrowId(p.trade_id)
    try {
      const env = await signRequest({
        action: 'set_trade_grow', wallet: address,
        body: { trade_id: p.trade_id, enabled: next }, signMessageAsync,
      })
      const r = await setTradeGrow(env, p.trade_id, next)
      setPositions(prev => (prev ?? []).map(x =>
        x.trade_id === p.trade_id ? { ...x, grow_mode: r.grow_mode } : x))
    } catch (e) {
      if (isUserRejection(e)) {
        setErr(isZh ? 'Grow 切换已取消' : 'Grow toggle cancelled')
      } else {
        setErr(walletErrorLabel(e, isZh ? 'Grow 切换已取消' : 'Grow toggle cancelled', 90)
               || (isZh ? 'Grow 切换失败' : 'grow toggle failed'))
      }
    } finally { setGrowId(null) }
  }

  useEffect(() => {
    if (!isConnected || !address) {
      setPositions(null); setToday(null); setNeedsUnlock(false); setErr(null)
      return
    }
    let cancelled = false

    // Only reuse a cached envelope here. Open positions should never trigger
    // a fresh signature popup on their own while the user is browsing.
    async function load() {
      const env = getCachedViewEnvelope('view_positions', address!)
        ?? getCachedViewEnvelope('view_user', address!)
      if (!env) {
        if (!cancelled) {
          setNeedsUnlock(true)
          setErr(null)
        }
        return
      }
      try {
        const [p, t] = await Promise.all([
          getOpenPositions(address!, env),
          getTodayStats(address!, env),
        ])
        if (!cancelled) {
          setPositions(p.positions); setToday(t); setErr(null); setNeedsUnlock(false)
        }
      } catch (e: unknown) {
        if (!cancelled) setErr(e instanceof Error ? e.message.slice(0, 80) : (isZh ? '加载失败' : 'fetch error'))
      }
    }

    void load()
    const id = setInterval(() => { void load() }, POLL_MS)
    return () => { cancelled = true; clearInterval(id) }
  }, [address, isConnected, signMessageAsync, isZh])

  // Trigger close. Two-step: opens modal, user confirms, we sign + POST.
  async function confirmCloseTrade() {
    if (!address || !closing) return
    setCloseErr(''); setCloseState('signing')
    try {
      const env = await signRequest({
        action: 'close_trade',
        wallet: address,
        body:   { trade_id: closing.trade_id },
        signMessageAsync,
      })
      setCloseState('closing')
      await manualCloseTrade(env, closing.trade_id)
      // Optimistically drop the row from the list; the next poll will confirm.
      setPositions(prev => (prev ?? []).filter(x => x.trade_id !== closing.trade_id))
      setClosing(null)
      setCloseState('idle')
    } catch (e: unknown) {
      setCloseErr(walletErrorLabel(e, isZh ? '已取消' : 'Cancelled', 120))
      setCloseState('err')
    }
  }

  // Return null both before mount (SSR) and when not connected — same output,
  // no hydration mismatch.
  if (!mounted || !isConnected) return null
  if (needsUnlock && positions === null && today === null) {
    return (
      <div className="card" style={{ padding: 16, marginBottom: 16 }}>
        <div style={{ fontSize: 11, color: 'var(--ink-3)', letterSpacing: '0.06em', textTransform: 'uppercase', fontWeight: 600, marginBottom: 6 }}>
          Open positions
        </div>
        <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--ink)' }}>
          Sign in once to view open positions
        </div>
        <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 4, lineHeight: 1.6 }}>
          Go to the <strong>Settings page</strong> and click <em>Sign in to view your settings</em>. After signing, your open positions will appear here automatically.
        </div>
      </div>
    )
  }
  if (positions === null && today === null) return null

  const totalUnrealized = (positions ?? []).reduce(
    (s, p) => s + (p.unrealized_usd ?? 0), 0,
  )
  const pnlTone = today
    ? (today.realized_pnl_usd > 0 ? 'up' : today.realized_pnl_usd < 0 ? 'down' : 'idle')
    : 'idle'
  const todayColor = pnlTone === 'up' ? 'var(--up)' : pnlTone === 'down' ? 'var(--down)' : 'var(--ink-2)'

  return (
    <div className="card" style={{ padding: 0, marginBottom: 16, overflow: 'hidden' }}>
      {/* Header strip — at-a-glance status */}
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '14px 18px', flexWrap: 'wrap', gap: 12,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 18, flexWrap: 'wrap' }}>
          <div>
            <div style={{ fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.06em',
                          textTransform: 'uppercase', fontWeight: 600, marginBottom: 2 }}>
              Open
            </div>
            <div style={{ fontSize: 18, fontWeight: 700 }}>
              {today?.open_count ?? 0}
              <span style={{ fontSize: 12, color: 'var(--ink-3)', marginLeft: 6, fontWeight: 400 }}>
                {`position${(today?.open_count ?? 0) === 1 ? '' : 's'}`}
              </span>
            </div>
          </div>

          <div style={{ width: 1, height: 32, background: 'var(--line)' }} />

          <div>
            <div style={{ fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.06em',
                          textTransform: 'uppercase', fontWeight: 600, marginBottom: 2 }}>
              Unrealized
            </div>
            <div style={{ fontSize: 18, fontWeight: 700,
                          color: totalUnrealized > 0 ? 'var(--up)' :
                                 totalUnrealized < 0 ? 'var(--down)' : 'var(--ink-2)',
                          fontVariantNumeric: 'tabular-nums' }}>
              {fmtMoney(totalUnrealized, { sign: true })}
            </div>
          </div>

          <div style={{ width: 1, height: 32, background: 'var(--line)' }} />

          <div>
            <div style={{ fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.06em',
                          textTransform: 'uppercase', fontWeight: 600, marginBottom: 2 }}>
              Today&apos;s realized
            </div>
            <div style={{ fontSize: 18, fontWeight: 700, color: todayColor,
                          fontVariantNumeric: 'tabular-nums' }}>
              {fmtMoney(today?.realized_pnl_usd ?? 0, { sign: true })}
            </div>
            <div style={{ fontSize: 10, color: 'var(--ink-3)', marginTop: 1 }}>
              {today ? `${today.trades_closed} closed · ${today.wins}W · ${today.losses}L` : '—'}
            </div>
            {today != null && (today.open_realized_usd ?? 0) !== 0 && (
              <div style={{ fontSize: 10, color: 'var(--ink-3)', marginTop: 1 }}>
                {`incl. ${fmtMoney(today.open_realized_usd, { sign: true })} locked in on open trades`}
              </div>
            )}
          </div>
        </div>

        {err && (
          <span style={{ fontSize: 11, color: 'var(--down)' }}>● {err}</span>
        )}
      </div>

      {/* Position list (or empty state) */}
      {positions && positions.length > 0 ? (
        <div>
          <div style={{
            display: 'grid',
            gridTemplateColumns: '70px 60px 1fr 1fr 80px 1fr 90px',
            gap: 12,
            padding: '8px 14px',
            background: 'var(--bg-sunk)',
            fontSize: 10, fontWeight: 600, letterSpacing: '0.05em',
            color: 'var(--ink-3)', textTransform: 'uppercase',
          }}>
            <span>Asset</span><span>Side</span><span>Prices</span>
            <span>Size</span><span>Hold</span>
            <span style={{ textAlign: 'right' }}>Unrealized</span>
            <span style={{ textAlign: 'right' }}>Action</span>
          </div>
          {positions.map(p => (
            <PositionRow
              key={p.trade_id}
              p={p}
              onClose={setClosing}
              onToggleGrow={toggleGrow}
              growBusy={growId === p.trade_id}
              isZh={isZh}
            />
          ))}
        </div>
      ) : (
        <div style={{
          borderTop: '1px solid var(--line)',
          padding: '20px 18px',
          fontSize: 13, color: 'var(--ink-3)', textAlign: 'center',
        }}>
          No open positions. When the bot opens a trade, it will show up here.
        </div>
      )}

      {/* ── Confirmation modal (P0.1 safety valve) ───────────────────
          Two-step UX so the wallet popup isn't surprising. The user
          presses "Close now", reads the impact summary, then confirms. */}
      {closing && (
        <div
          onClick={() => closeState === 'idle' && setClosing(null)}
          style={{
            position: 'fixed', inset: 0, zIndex: 1000,
            background: 'rgba(0,0,0,0.55)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            padding: 20,
          }}
        >
          <div
            onClick={e => e.stopPropagation()}
            className="card"
            style={{ padding: 24, maxWidth: 440, width: '100%' }}
          >
            <div style={{ fontSize: 16, fontWeight: 700, marginBottom: 4 }}>
              {isZh
                ? `现在平掉 ${closing.asset} ${closing.side === 'long' ? '多单' : '空单'}？`
                : `Close ${closing.side === 'long' ? 'long' : 'short'} ${closing.asset} now?`}
            </div>
            <div style={{ fontSize: 12, color: 'var(--ink-3)', marginBottom: 16 }}>
              {closing.is_paper
                ? (isZh ? '这是模拟交易，平仓只做本地记录，不会调用 Hyperliquid。' : 'Paper trade — synthetic close, no Hyperliquid call.')
                : (isZh ? '会向 Hyperliquid 发送 IOC 市价单。已实现盈亏将立即确认。' : 'Sends an IOC market order to Hyperliquid. Realised PnL is permanent.')}
            </div>
            <div style={{
              background: 'var(--bg-sunk)', borderRadius: 8, padding: 14, marginBottom: 16,
            }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 6 }}>
                <span style={{ color: 'var(--ink-3)' }}>{isZh ? '开仓价' : 'Entry'}</span>
                <span className="mono">{fmtMoney(closing.entry_price)}</span>
              </div>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 6 }}>
                <span style={{ color: 'var(--ink-3)' }}>{isZh ? '现价' : 'Mark'}</span>
                <span className="mono">{closing.current_price != null ? fmtMoney(closing.current_price) : (isZh ? '暂无' : 'n/a')}</span>
              </div>
              {closing.realized_usd != null && closing.realized_usd !== 0 && (
                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 6, color: 'var(--ink-3)' }}>
                  <span>{isZh ? '已锁定（降风险）' : 'Locked in (de-risked)'}</span>
                  <span className="mono">{fmtMoney(closing.realized_usd, { sign: true })}</span>
                </div>
              )}
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 13, fontWeight: 600, marginTop: 8, paddingTop: 8, borderTop: '1px solid var(--line)' }}>
                <span>{isZh ? '当前未平部分预估盈亏' : 'Est. PnL on open portion'}</span>
                <span style={{
                  color: (closing.unrealized_usd ?? 0) > 0 ? 'var(--up)'
                       : (closing.unrealized_usd ?? 0) < 0 ? 'var(--down)' : 'var(--ink-2)',
                  fontVariantNumeric: 'tabular-nums',
                }}>
                  {fmtMoney(closing.unrealized_usd, { sign: true })}
                  <span style={{ marginLeft: 6, opacity: 0.7, fontSize: 11 }}>
                    ({fmtPct(closing.unrealized_pct)})
                  </span>
                </span>
              </div>
            </div>
            {closeState === 'err' && (
              <div style={{ fontSize: 12, color: 'var(--down)', marginBottom: 12 }}>{closeErr}</div>
            )}
            <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end' }}>
              <button
                onClick={() => setClosing(null)}
                disabled={closeState === 'signing' || closeState === 'closing'}
                className="btn ghost"
                style={{ padding: '8px 16px', fontSize: 13 }}
              >
                {isZh ? '取消' : 'Cancel'}
              </button>
              <button
                onClick={confirmCloseTrade}
                disabled={closeState === 'signing' || closeState === 'closing'}
                className="btn"
                style={{
                  padding: '8px 18px', fontSize: 13, fontWeight: 600,
                  background: 'var(--down)', color: '#fff', border: 'none',
                }}
              >
                {closeState === 'signing' ? (isZh ? '钱包签名中…' : 'Sign in wallet…')
                  : closeState === 'closing' ? (isZh ? '平仓中…' : 'Closing…')
                  : (isZh ? `立即平掉 ${closing.asset}` : `Close ${closing.asset} now`)}
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  )
}
