import { useEffect, useMemo, useRef, useState } from 'react';
import type { KeyboardEvent, ReactNode } from 'react';
import { Link } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { usePaperTrades, useClosePaperTrade, useExitPolicy } from '../../hooks/usePaperTrades';
import { useTickerNames } from '../../hooks/useTickers';
import { getOHLCV } from '../../api/ohlcv';
import { tradePnl } from '../../lib/paperTrade';
import { formatPrice } from '../../lib/format';
import { RBar, TradeChart } from '../charts/horizon';
import { Section } from '../ui/Section';
import { Callout } from '../ui/Callout';
import type { PaperTrade } from '../../lib/types';

function money(v: number): string {
  const sign = v >= 0 ? '+' : '−';
  return `${sign}$${Math.abs(v).toFixed(2)}`;
}
function pnlColor(v: number): string {
  if (v > 0) return 'text-emerald-300';
  if (v < 0) return 'text-red-300';
  return 'text-gray-300';
}

function DirTag({ direction }: { direction: string }) {
  const isLong = direction === 'long';
  return (
    <span className={`num inline-block rounded px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wider ${
      isLong ? 'bg-emerald-500/15 text-emerald-300' : 'bg-red-500/15 text-red-300'
    }`}>
      {direction}
    </span>
  );
}

function Detail({ label, value, valueClass = 'text-gray-100' }: {
  label: string;
  value: ReactNode;
  valueClass?: string;
}) {
  return (
    <div>
      <dt className="num text-[9.5px] uppercase tracking-[0.16em] text-gray-500">{label}</dt>
      <dd className={`num mt-0.5 text-sm ${valueClass}`}>{value}</dd>
    </div>
  );
}

/** Expanded row: full trade detail + price chart with entry / trail path. */
function TradeDetail({ trade, exitLabel, exitMode, atrMultiplier, trailingPct, onClose, closing }: {
  trade: PaperTrade;
  exitLabel: string | null;
  exitMode: 'time' | 'trailing' | 'atr_trailing' | 'target';
  atrMultiplier: number;
  trailingPct: number;
  onClose: () => void;
  closing: boolean;
}) {
  const p = tradePnl(trade);
  const stopLevel = trade.trailing_stop ?? trade.stop_loss;
  const trailMoved = trade.trailing_stop != null
    && Math.abs(trade.trailing_stop - trade.stop_loss) > 1e-6;
  const ohlcv = useQuery({
    queryKey: ['ohlcv', trade.symbol],
    queryFn: () => getOHLCV(trade.symbol),
    staleTime: 5 * 60_000,
  });
  const opened = new Date(trade.opened_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
  const chartHint = exitMode === 'target'
    ? 'since entry · entry / stop / target'
    : exitMode === 'time'
      ? 'since entry · entry / stop'
      : 'since entry · entry / initial stop / trail';
  return (
    <div className="flex flex-col gap-4 px-2 pb-4 pt-1">
      <dl className="grid grid-cols-2 gap-x-8 gap-y-3 sm:grid-cols-4">
        <Detail label="opened" value={`${opened} · ${trade.shares} shares`} />
        <Detail label="entry → now" value={
          `${formatPrice(trade.entry_price)} → ${trade.current_price != null ? formatPrice(trade.current_price) : '—'}`
        } />
        <Detail
          label="P&L"
          value={p ? `${money(p.pnl)} · ${p.pct >= 0 ? '+' : ''}${p.pct.toFixed(1)}%` : '—'}
          valueClass={p ? pnlColor(p.pnl) : 'text-gray-500'}
        />
        <Detail
          label="alpha vs SPY"
          value={
            trade.alpha_pct != null
              ? `${trade.alpha_pct >= 0 ? '+' : ''}${trade.alpha_pct.toFixed(1)}%${trade.alpha_usd != null ? ` · ${money(trade.alpha_usd)}` : ''}`
              : '—'
          }
          valueClass={trade.alpha_pct != null ? pnlColor(trade.alpha_pct) : 'text-gray-500'}
        />
        <Detail
          label={trailMoved ? 'trail' : 'stop'}
          value={
            <>
              {formatPrice(stopLevel)}
              {trade.trailing_stop != null && (
                <span className="ml-1.5 text-[10px] text-gray-500">
                  {trailMoved ? 'trailing' : 'at initial'}
                  {trade.trailing_distance_pct != null ? ` · ${Math.abs(trade.trailing_distance_pct).toFixed(1)}% away` : ''}
                </span>
              )}
            </>
          }
        />
        <Detail
          label="target"
          value={
            <>
              {formatPrice(trade.target)}
              {exitMode !== 'target' && (
                <span className="ml-1.5 text-[10px] text-gray-500">screening only</span>
              )}
            </>
          }
        />
        <Detail label="exit rule" value={exitLabel ?? 'target/stop'} />
        <div className="flex items-end">
          <button
            onClick={onClose}
            disabled={closing}
            className="rounded-md border border-white/[0.1] px-3 py-1.5 text-xs text-gray-300 transition-colors hover:bg-white/[0.06] hover:text-white disabled:opacity-50"
          >
            Sell at market
          </button>
        </div>
      </dl>
      {ohlcv.data && (
        <div>
          <p className="num text-[9.5px] uppercase tracking-[0.16em] text-gray-500">
            {chartHint}
          </p>
          <div className="mt-2">
            <TradeChart
              direction={trade.direction}
              entry={trade.entry_price}
              initialStop={trade.stop_loss}
              target={trade.target}
              bars={ohlcv.data}
              openedAt={trade.opened_at}
              exitMode={exitMode}
              atrMultiplier={atrMultiplier}
              trailingPct={trailingPct}
            />
          </div>
        </div>
      )}
    </div>
  );
}

export function OpenTradesPanel() {
  const { data: trades, isLoading } = usePaperTrades('open');
  const { data: policy } = useExitPolicy();
  const tickerNames = useTickerNames();
  const close = useClosePaperTrade();
  const [expandedId, setExpandedId] = useState<number | null>(null);

  // Open the first row once on load so the trade chart is visible without a
  // click; after that the user's expand/collapse choice wins.
  const autoExpanded = useRef(false);
  useEffect(() => {
    if (!autoExpanded.current && trades && trades.length > 0) {
      autoExpanded.current = true;
      setExpandedId(trades[0].id);
    }
  }, [trades]);

  const exitMode = policy?.mode ?? 'atr_trailing';
  const atrMultiplier = policy?.atr_multiplier ?? 3;
  const trailingPct = policy?.trailing_pct ?? 12;
  const exitLabel = policy
    ? policy.mode === 'atr_trailing'
      ? `${atrMultiplier.toFixed(1)}x ATR trailing stop / ${policy.hold_days}d max`
      : policy.mode === 'trailing'
        ? `trailing ${Math.round(trailingPct)}%`
        : policy.mode === 'time'
          ? `${policy.hold_days}d hold`
          : 'target/stop'
    : null;

  const rows = trades ?? [];

  const { totals, rMax } = useMemo(() => {
    let pnl = 0, winners = 0, losers = 0, alphaUsd = 0, alphaPriced = 0, rMax = 1;
    for (const t of rows) {
      const p = tradePnl(t);
      if (p) {
        pnl += p.pnl;
        if (p.pnl > 0) winners += 1;
        else if (p.pnl < 0) losers += 1;
        if (p.r != null) rMax = Math.max(rMax, Math.abs(p.r));
      }
      if (t.alpha_usd != null) { alphaUsd += t.alpha_usd; alphaPriced += 1; }
    }
    return { totals: { pnl, winners, losers, alphaUsd, alphaPriced }, rMax };
  }, [rows]);

  if (isLoading) return null;

  return (
    <Section
      title="Open Positions"
      hint={rows.length > 0
        ? `${rows.length} open · ${totals.winners}▲ ${totals.losers}▼ · R-multiple to entry · select a row for detail`
        : 'paper trading'}
    >
      {rows.length === 0 ? (
        <Callout variant="empty">
          No open paper trades. Open a ticker and tap “Mark as taken” on a setup to start.
        </Callout>
      ) : (
        <div className="glass px-4 py-1">
          <ul className="divide-y divide-white/[0.04]">
            {rows.map((t) => {
              const p = tradePnl(t);
              const open = expandedId === t.id;
              return (
                <li key={t.id}>
                  <div
                    role="button"
                    tabIndex={0}
                    onClick={() => setExpandedId(open ? null : t.id)}
                    onKeyDown={(e: KeyboardEvent) => {
                      if (e.key === 'Enter' || e.key === ' ') {
                        e.preventDefault();
                        setExpandedId(open ? null : t.id);
                      }
                    }}
                    aria-expanded={open}
                    className="grid w-full cursor-pointer grid-cols-[110px_1fr_60px_16px] items-center gap-3 rounded-lg px-2 py-2.5 text-left transition-colors hover:bg-white/[0.03] sm:grid-cols-[130px_150px_1fr_70px_16px]"
                  >
                    <span className="flex items-center gap-2">
                      <Link
                        to={`/ticker/${t.symbol}`}
                        onClick={(e) => e.stopPropagation()}
                        className="font-medium text-blue-300 transition-colors hover:text-blue-200"
                      >
                        {t.symbol}
                      </Link>
                      <DirTag direction={t.direction} />
                    </span>
                    <span className="num hidden text-xs text-gray-400 sm:block">
                      {formatPrice(t.entry_price)} → {t.current_price != null ? formatPrice(t.current_price) : '—'}
                    </span>
                    <RBar r={p?.r ?? null} max={rMax} />
                    <span className={`num text-right text-[13px] font-semibold ${p?.r != null ? pnlColor(p.r) : 'text-gray-500'}`}>
                      {p?.r != null ? `${p.r >= 0 ? '+' : ''}${p.r.toFixed(2)}R` : '—'}
                    </span>
                    <span className={`text-[10px] text-gray-500 transition-transform ${open ? 'rotate-180' : ''}`} aria-hidden="true">
                      ▾
                    </span>
                  </div>
                  {open && (
                    <TradeDetail
                      trade={t}
                      exitLabel={exitLabel}
                      exitMode={exitMode}
                      atrMultiplier={atrMultiplier}
                      trailingPct={trailingPct}
                      closing={close.isPending}
                      onClose={() => {
                        if (window.confirm(`Close ${t.shares} ${t.symbol} at the current price?`)) {
                          close.mutate({ id: t.id });
                        }
                      }}
                    />
                  )}
                  {/* company name for screen readers / row context */}
                  <span className="sr-only">{tickerNames.get(t.symbol.toUpperCase()) ?? ''}</span>
                </li>
              );
            })}
          </ul>
          <div className="flex flex-wrap items-baseline justify-between gap-2 border-t border-white/[0.06] px-2 py-2.5 text-xs text-gray-500">
            <span>total unrealized · alpha vs S&P 500{exitLabel ? ` · auto-exit: ${exitLabel}` : ''}</span>
            <span className="num flex gap-4">
              <b className={`font-semibold ${pnlColor(totals.pnl)}`}>{money(totals.pnl)}</b>
              <b className={`font-semibold ${totals.alphaPriced > 0 ? pnlColor(totals.alphaUsd) : 'text-gray-500'}`}>
                {totals.alphaPriced > 0 ? money(totals.alphaUsd) : '—'}
              </b>
            </span>
          </div>
        </div>
      )}
    </Section>
  );
}
