import React, { useEffect, useMemo, useRef, useState } from 'react';
import { ResponsiveContainer, LineChart, Line, XAxis, YAxis, Tooltip, CartesianGrid, ReferenceLine } from 'recharts';
import type { BacktestResult } from '../types';
import { buildInsightCards, toEquitySeries } from '../utils';

interface BacktestResultsDashboardProps {
    result: BacktestResult;
}

const money = (value: number): string => {
    const amount = Number(value || 0);
    return amount.toLocaleString(undefined, { style: 'currency', currency: 'USD', maximumFractionDigits: 2 });
};

const pct = (value: number): string => `${Number(value || 0).toFixed(2)}%`;

export const BacktestResultsDashboard: React.FC<BacktestResultsDashboardProps> = ({ result }) => {
    const equitySeries = useMemo(() => toEquitySeries(result), [result]);
    const [cursorIndex, setCursorIndex] = useState(0);
    const [isPlaying, setIsPlaying] = useState(false);
    const [speed, setSpeed] = useState<'1x' | '5x' | '20x' | 'instant'>('1x');
    const tradeRowRefs = useRef<Record<string, HTMLTableRowElement | null>>({});
    const insightCards = useMemo(() => buildInsightCards(result), [result]);
    const orderedTrades = useMemo(
        () => [...result.trades].sort((a, b) => a.entryTimestamp - b.entryTimestamp),
        [result.trades]
    );

    useEffect(() => {
        setCursorIndex(0);
        setIsPlaying(false);
        setSpeed('1x');
    }, [result]);

    useEffect(() => {
        if (!isPlaying) return;
        if (!equitySeries.length) return;
        if (speed === 'instant') {
            setCursorIndex(equitySeries.length - 1);
            setIsPlaying(false);
            return;
        }

        const tickMs = speed === '1x' ? 700 : speed === '5x' ? 200 : 80;
        const timer = window.setInterval(() => {
            setCursorIndex((prev) => {
                const atEnd = prev >= equitySeries.length - 1;
                if (atEnd) {
                    setIsPlaying(false);
                    return prev;
                }
                return prev + 1;
            });
        }, tickMs);
        return () => window.clearInterval(timer);
    }, [isPlaying, speed, equitySeries.length]);

    const cursorPoint = equitySeries[Math.min(cursorIndex, Math.max(0, equitySeries.length - 1))];
    const cursorTimestamp = Number(cursorPoint?.timestamp ?? result.window.fromTimestamp);
    const activeTrade = useMemo(() => {
        if (!orderedTrades.length) return null;
        return orderedTrades.find((trade) => (
            cursorTimestamp >= trade.entryTimestamp && cursorTimestamp <= trade.exitTimestamp
        )) || null;
    }, [cursorTimestamp, orderedTrades]);

    useEffect(() => {
        if (!activeTrade) return;
        const row = tradeRowRefs.current[activeTrade.id];
        if (row && typeof row.scrollIntoView === 'function') {
            row.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
        }
    }, [activeTrade]);

    const replayInsight = useMemo(() => {
        const topBlocked = Object.entries(result.diagnostics.blockedRuleCounts || {})
            .sort((a, b) => b[1] - a[1])[0];
        if (activeTrade) {
            return `Active trade ${activeTrade.symbol} (${activeTrade.side}). Entry: ${activeTrade.entryReason}. Exit trigger: ${activeTrade.exitReason}.`;
        }
        const nextTrade = orderedTrades.find((trade) => trade.entryTimestamp > cursorTimestamp);
        if (nextTrade) {
            if (topBlocked) {
                return `No trade - rule failed (${topBlocked[0]}). Next trade starts at ${new Date(nextTrade.entryTimestamp).toLocaleString()}.`;
            }
            return `No trade - rule failed or no valid signal. Next trade starts at ${new Date(nextTrade.entryTimestamp).toLocaleString()}.`;
        }
        if (topBlocked) {
            return `No trade - rule failed (${topBlocked[0]}). Replay window ended.`;
        }
        return 'No trade - rule failed or no qualifying setup during this replay segment.';
    }, [activeTrade, cursorTimestamp, orderedTrades, result.diagnostics.blockedRuleCounts]);

    const isAtEnd = cursorIndex >= Math.max(0, equitySeries.length - 1);

    return (
        <div className="space-y-5">
            <div data-testid="backtest-replay-controls" className="rounded-2xl border border-cyan-500/30 bg-cyan-500/5 p-4 space-y-3">
                <div className="flex flex-wrap items-center justify-between gap-3">
                    <h3 className="text-sm font-bold uppercase tracking-wider text-cyan-200">Replay Controls (UI-Only)</h3>
                    <span className="text-[11px] text-cyan-100/80">
                        Replay window: {result.window.fromIso.slice(0, 10)}{' -> '}{result.window.toIso.slice(0, 10)} ({result.window.timezone})
                    </span>
                </div>
                <div className="flex flex-wrap items-center gap-2">
                    <button
                        type="button"
                        onClick={() => setIsPlaying(true)}
                        disabled={isPlaying || !equitySeries.length || isAtEnd}
                        className={`rounded-lg px-3 py-1 text-[11px] font-bold uppercase tracking-wide ${isPlaying || isAtEnd ? 'bg-zinc-800 text-zinc-500' : 'bg-emerald-400 text-black hover:bg-emerald-300'}`}
                    >
                        Play
                    </button>
                    <button
                        type="button"
                        onClick={() => setIsPlaying(false)}
                        disabled={!isPlaying}
                        className={`rounded-lg px-3 py-1 text-[11px] font-bold uppercase tracking-wide ${!isPlaying ? 'bg-zinc-800 text-zinc-500' : 'bg-zinc-200 text-black hover:bg-white'}`}
                    >
                        Pause
                    </button>
                    <button
                        type="button"
                        onClick={() => setCursorIndex((prev) => Math.min(prev + 1, Math.max(0, equitySeries.length - 1)))}
                        disabled={!equitySeries.length || isAtEnd}
                        className={`rounded-lg px-3 py-1 text-[11px] font-bold uppercase tracking-wide ${isAtEnd ? 'bg-zinc-800 text-zinc-500' : 'bg-indigo-400 text-black hover:bg-indigo-300'}`}
                    >
                        Step
                    </button>
                    <select
                        value={speed}
                        onChange={(event) => setSpeed(event.target.value as '1x' | '5x' | '20x' | 'instant')}
                        className="rounded-lg border border-white/10 bg-zinc-900 px-2 py-1 text-[11px] text-white"
                    >
                        <option value="1x">1x</option>
                        <option value="5x">5x</option>
                        <option value="20x">20x</option>
                        <option value="instant">Instant</option>
                    </select>
                    <button
                        type="button"
                        onClick={() => {
                            setIsPlaying(false);
                            setCursorIndex(0);
                        }}
                        className="rounded-lg px-3 py-1 text-[11px] font-bold uppercase tracking-wide bg-white/10 text-zinc-300 hover:bg-white/20"
                    >
                        Reset
                    </button>
                </div>
                <div className="grid grid-cols-1 md:grid-cols-2 gap-2 text-xs text-cyan-100/90">
                    <div data-testid="backtest-replay-cursor">
                        <span className="text-cyan-300/70">Cursor:</span> {new Date(cursorTimestamp).toLocaleString()}
                    </div>
                    <div>
                        <span className="text-cyan-300/70">Insight:</span> {replayInsight}
                    </div>
                </div>
                <p className="text-[11px] text-cyan-100/80">
                    Replay shows a historical simulation. No real or paper trades are placed.
                </p>
            </div>

            <div className="rounded-2xl border border-white/10 bg-zinc-950/70 p-4 space-y-3">
                <h3 className="text-sm font-bold uppercase tracking-wider text-white">Execution Assumptions</h3>
                <div data-testid="backtest-assumptions-panel" className="grid grid-cols-1 md:grid-cols-2 gap-2 text-xs text-zinc-300">
                    <div><span className="text-zinc-500">Fill Model:</span> {result.assumptions.fillModel}</div>
                    <div><span className="text-zinc-500">Slippage:</span> {result.assumptions.slippageModel}</div>
                    <div><span className="text-zinc-500">Fees:</span> {result.assumptions.feeModel}</div>
                    <div><span className="text-zinc-500">Latency:</span> {result.assumptions.latencyModel}</div>
                    <div><span className="text-zinc-500">Intra-candle:</span> {result.assumptions.intraCandleModel}</div>
                    <div><span className="text-zinc-500">Trigger Resolution:</span> {result.assumptions.triggerResolution}</div>
                    <div><span className="text-zinc-500">Warm-up Enforced:</span> {result.assumptions.warmupEnforced ? 'Yes' : 'No'}</div>
                    <div><span className="text-zinc-500">Deterministic Replay:</span> {result.assumptions.deterministicReplay ? 'Yes' : 'No'}</div>
                    <div><span className="text-zinc-500">Replay Window:</span> {result.assumptions.replayWindow}</div>
                    <div><span className="text-zinc-500">Window End Policy:</span> {result.assumptions.endOfWindowPolicy}</div>
                </div>
                <p className="text-[11px] text-amber-300">{result.assumptions.disclaimer}</p>
            </div>

            <div data-testid="backtest-warmup-meta" className="rounded-2xl border border-white/10 bg-zinc-950/70 p-4 grid grid-cols-2 md:grid-cols-4 gap-3">
                <div>
                    <p className="text-[10px] uppercase tracking-wider text-zinc-500">Warm-up Start</p>
                    <p className="text-xs text-white">{new Date(result.warmup.startTimestamp).toLocaleString()}</p>
                </div>
                <div>
                    <p className="text-[10px] uppercase tracking-wider text-zinc-500">Warm-up End</p>
                    <p className="text-xs text-white">{new Date(result.warmup.endTimestamp).toLocaleString()}</p>
                </div>
                <div>
                    <p className="text-[10px] uppercase tracking-wider text-zinc-500">Candles Required</p>
                    <p className="text-xs text-white">
                        15m {result.warmup.candlesRequired['15m']} | 1h {result.warmup.candlesRequired['1h']} | 4h {result.warmup.candlesRequired['4h']}
                    </p>
                </div>
                <div>
                    <p className="text-[10px] uppercase tracking-wider text-zinc-500">Signals Ignored</p>
                    <p className="text-xs text-white">{result.warmup.signalsIgnored}</p>
                </div>
            </div>

            <div className="grid grid-cols-2 md:grid-cols-5 gap-3">
                <div className="rounded-xl border border-white/10 bg-zinc-950/70 p-3">
                    <p className="text-[10px] uppercase tracking-wider text-zinc-500">Net PnL</p>
                    <p className="text-sm font-bold text-white">{money(result.summary.netPnlUsd)}</p>
                </div>
                <div className="rounded-xl border border-white/10 bg-zinc-950/70 p-3">
                    <p className="text-[10px] uppercase tracking-wider text-zinc-500">Win Rate</p>
                    <p className="text-sm font-bold text-white">{pct(result.summary.winRate)}</p>
                </div>
                <div className="rounded-xl border border-white/10 bg-zinc-950/70 p-3">
                    <p className="text-[10px] uppercase tracking-wider text-zinc-500">Max Drawdown</p>
                    <p className="text-sm font-bold text-white">{pct(result.summary.maxDrawdownPct)}</p>
                </div>
                <div className="rounded-xl border border-white/10 bg-zinc-950/70 p-3">
                    <p className="text-[10px] uppercase tracking-wider text-zinc-500">Sharpe</p>
                    <p className="text-sm font-bold text-white">{result.summary.sharpe.toFixed(3)}</p>
                </div>
                <div className="rounded-xl border border-white/10 bg-zinc-950/70 p-3">
                    <p className="text-[10px] uppercase tracking-wider text-zinc-500">Total Trades</p>
                    <p className="text-sm font-bold text-white">{result.summary.totalTrades}</p>
                </div>
            </div>

            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                <div className="rounded-2xl border border-white/10 bg-zinc-950/70 p-3">
                    <h4 className="text-xs font-bold uppercase tracking-wider text-zinc-300 mb-2">Equity Curve</h4>
                    <div style={{ width: '100%', height: 220 }}>
                        <ResponsiveContainer>
                            <LineChart data={equitySeries}>
                                <CartesianGrid stroke="#222" strokeDasharray="3 3" />
                                <XAxis
                                    dataKey="timestamp"
                                    tickFormatter={(value) => new Date(Number(value)).toLocaleDateString()}
                                    tick={{ fontSize: 10, fill: '#888' }}
                                />
                                <YAxis tick={{ fontSize: 10, fill: '#888' }} />
                                <Tooltip
                                    formatter={(value: any) => money(Number(value))}
                                    labelFormatter={(label) => new Date(Number(label)).toLocaleString()}
                                />
                                <ReferenceLine x={cursorTimestamp} stroke="#06b6d4" strokeWidth={1.5} strokeDasharray="4 4" />
                                <Line type="monotone" dataKey="equityUsd" stroke="#22c55e" strokeWidth={2} dot={false} />
                            </LineChart>
                        </ResponsiveContainer>
                    </div>
                </div>
                <div className="rounded-2xl border border-white/10 bg-zinc-950/70 p-3">
                    <h4 className="text-xs font-bold uppercase tracking-wider text-zinc-300 mb-2">Drawdown Curve</h4>
                    <div style={{ width: '100%', height: 220 }}>
                        <ResponsiveContainer>
                            <LineChart data={equitySeries}>
                                <CartesianGrid stroke="#222" strokeDasharray="3 3" />
                                <XAxis
                                    dataKey="timestamp"
                                    tickFormatter={(value) => new Date(Number(value)).toLocaleDateString()}
                                    tick={{ fontSize: 10, fill: '#888' }}
                                />
                                <YAxis tick={{ fontSize: 10, fill: '#888' }} />
                                <Tooltip
                                    formatter={(value: any) => pct(Number(value))}
                                    labelFormatter={(label) => new Date(Number(label)).toLocaleString()}
                                />
                                <ReferenceLine x={cursorTimestamp} stroke="#06b6d4" strokeWidth={1.5} strokeDasharray="4 4" />
                                <Line type="monotone" dataKey="drawdownPct" stroke="#f97316" strokeWidth={2} dot={false} />
                            </LineChart>
                        </ResponsiveContainer>
                    </div>
                </div>
            </div>

            <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
                {insightCards.map((card) => (
                    <div key={card.title} className="rounded-xl border border-white/10 bg-zinc-950/70 p-3">
                        <p className="text-[10px] uppercase tracking-wider text-zinc-500">{card.title}</p>
                        <p className="text-sm font-bold text-white mt-1">{card.value}</p>
                        <p className="text-[11px] text-zinc-400 mt-1">{card.detail}</p>
                    </div>
                ))}
            </div>

            {result.openPositionsAtEnd.length > 0 && (
                <div className="rounded-2xl border border-amber-500/30 bg-amber-500/10 p-4">
                    <h4 className="text-xs font-bold uppercase tracking-wider text-amber-200 mb-2">Open At End</h4>
                    <div className="space-y-2">
                        {result.openPositionsAtEnd.map((position) => (
                            <div key={`${position.symbol}-${position.entryTimestamp}`} className="grid grid-cols-1 md:grid-cols-5 gap-2 text-xs text-amber-100">
                                <div>{position.symbol} {position.side}</div>
                                <div>Entry {new Date(position.entryTimestamp).toLocaleString()}</div>
                                <div>Size {position.size}</div>
                                <div>Unrealized {money(position.unrealizedPnlUsd)} ({pct(position.unrealizedPnlPct)})</div>
                                <div>{position.status}</div>
                            </div>
                        ))}
                    </div>
                </div>
            )}

            <div className="rounded-2xl border border-white/10 bg-zinc-950/70 overflow-hidden">
                <div className="px-4 py-3 border-b border-white/10">
                    <h4 className="text-xs font-bold uppercase tracking-wider text-zinc-300">Trades</h4>
                </div>
                <div className="overflow-x-auto max-h-[360px]">
                    <table className="w-full text-left text-xs">
                        <thead className="bg-zinc-900 text-zinc-500 uppercase tracking-wider text-[10px]">
                            <tr>
                                <th className="px-3 py-2">Symbol</th>
                                <th className="px-3 py-2">Side</th>
                                <th className="px-3 py-2">Entry</th>
                                <th className="px-3 py-2">Exit</th>
                                <th className="px-3 py-2">PnL</th>
                                <th className="px-3 py-2">Reasoning</th>
                            </tr>
                        </thead>
                        <tbody className="divide-y divide-white/5">
                            {result.trades.map((trade) => (
                                <tr
                                    key={trade.id}
                                    ref={(element) => { tradeRowRefs.current[trade.id] = element; }}
                                    data-trade-id={trade.id}
                                    className={`${activeTrade?.id === trade.id ? 'bg-cyan-500/15' : 'hover:bg-white/5'}`}
                                >
                                    <td className="px-3 py-2 text-white">{trade.symbol}</td>
                                    <td className="px-3 py-2 text-zinc-300">{trade.side}</td>
                                    <td className="px-3 py-2 text-zinc-300">{new Date(trade.entryTimestamp).toLocaleString()}</td>
                                    <td className="px-3 py-2 text-zinc-300">{new Date(trade.exitTimestamp).toLocaleString()}</td>
                                    <td className={`px-3 py-2 font-semibold ${trade.pnlUsd >= 0 ? 'text-emerald-400' : 'text-rose-400'}`}>
                                        {money(trade.pnlUsd)} ({pct(trade.pnlPct)})
                                    </td>
                                    <td className="px-3 py-2 text-zinc-400">
                                        <div>{trade.entryReason}</div>
                                        <div className="text-zinc-500">Exit: {trade.exitReason}</div>
                                    </td>
                                </tr>
                            ))}
                            {result.trades.length === 0 && (
                                <tr>
                                    <td className="px-3 py-8 text-center text-zinc-500" colSpan={6}>
                                        No trades were executed during this replay window.
                                    </td>
                                </tr>
                            )}
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    );
};
