import React, { useMemo, useState } from 'react';
import type {
    BacktestIntraCandlePolicy,
    BacktestRequestPayload,
    BacktestTimeframe,
    BacktestTriggerTimeframe
} from '../types';
import { parseSymbolsInput, toDateInputValue } from '../utils';

type SourceType = 'csv' | 'json' | 'replay' | 'kraken';

interface BacktestConfiguratorProps {
    profileId?: string;
    strategyConfig: any;
    initialSymbols: string[];
    initialCapitalUsd?: number;
    onRun: (payload: BacktestRequestPayload) => Promise<void> | void;
    running?: boolean;
}

export const BacktestConfigurator: React.FC<BacktestConfiguratorProps> = ({
    profileId,
    strategyConfig,
    initialSymbols,
    initialCapitalUsd = 1000,
    onRun,
    running = false
}) => {
    const now = Date.now();
    const defaultFrom = toDateInputValue(now - (30 * 24 * 60 * 60 * 1000));
    const defaultTo = toDateInputValue(now);

    const [symbolsInput, setSymbolsInput] = useState((initialSymbols || []).join(', '));
    const [timeframe, setTimeframe] = useState<BacktestTimeframe>('15m');
    const [fromDate, setFromDate] = useState(defaultFrom);
    const [toDate, setToDate] = useState(defaultTo);
    const [sourceType, setSourceType] = useState<SourceType>('csv');
    const [sourcePayload, setSourcePayload] = useState<any>(null);
    const [sourceName, setSourceName] = useState('');
    const [initialCapital, setInitialCapital] = useState(initialCapitalUsd);
    const [slippageBps, setSlippageBps] = useState(5);
    const [feeBps, setFeeBps] = useState(10);
    const [partialFillPct, setPartialFillPct] = useState(1);
    const [fillOnNextBar, setFillOnNextBar] = useState(true);
    const [intraCandlePolicy, setIntraCandlePolicy] = useState<BacktestIntraCandlePolicy>('ohlc_path');
    const [triggerTimeframe, setTriggerTimeframe] = useState<BacktestTriggerTimeframe>('1m');
    const [forceCloseAtWindowEnd, setForceCloseAtWindowEnd] = useState(false);
    const [krakenLookbackCandles, setKrakenLookbackCandles] = useState(2000);
    const [error, setError] = useState<string | null>(null);

    const parsedSymbols = useMemo(() => parseSymbolsInput(symbolsInput), [symbolsInput]);

    const readFile = async (file: File): Promise<void> => {
        const text = await file.text();
        setSourceName(file.name);
        if (sourceType === 'csv') {
            setSourcePayload(text);
            return;
        }
        try {
            const parsed = JSON.parse(text);
            setSourcePayload(parsed);
        } catch {
            throw new Error('Failed to parse JSON file.');
        }
    };

    const handleRun = async () => {
        setError(null);
        if (!parsedSymbols.length) {
            setError('Please provide at least one symbol.');
            return;
        }
        if (!fromDate || !toDate) {
            setError('Please provide both from/to dates.');
            return;
        }
        if (new Date(`${toDate}T23:59:59.999Z`).getTime() < new Date(`${fromDate}T00:00:00.000Z`).getTime()) {
            setError('To date must be greater than or equal to From date.');
            return;
        }
        if (sourceType !== 'kraken' && !sourcePayload) {
            setError('Please upload historical data (CSV/JSON/Replay JSON) before running.');
            return;
        }
        if (!strategyConfig) {
            setError('Strategy configuration is required.');
            return;
        }

        const payload: BacktestRequestPayload = {
            mode: 'backtest',
            profileId,
            strategyConfig,
            symbols: parsedSymbols,
            timeframe,
            dateRange: {
                from: new Date(`${fromDate}T00:00:00.000Z`).toISOString(),
                to: new Date(`${toDate}T23:59:59.999Z`).toISOString()
            },
            dataSource: {
                type: sourceType,
                payload: sourceType === 'kraken'
                    ? {
                        exchange: 'kraken',
                        lookbackCandles: Number(krakenLookbackCandles || 2000)
                    }
                    : (sourceType === 'csv' ? String(sourcePayload || '') : sourcePayload)
            },
            execution: {
                initialCapitalUsd: Number(initialCapital || 0),
                orderType: 'market',
                slippageBps: Number(slippageBps),
                feeBps: Number(feeBps),
                partialFillPct: Number(partialFillPct),
                fillOnNextBar,
                intraCandlePolicy,
                triggerTimeframe,
                enforceWarmup: true,
                allowNegativeCash: false,
                forceCloseAtWindowEnd
            }
        };

        await onRun(payload);
    };

    return (
        <div className="space-y-4 p-4 rounded-2xl border border-white/10 bg-zinc-950/70">
            <div className="flex items-center justify-between">
                <h3 className="text-sm font-bold uppercase tracking-wider text-white">Backtest Configuration</h3>
                <span className="text-[10px] text-zinc-500 uppercase">No JSON editing required</span>
            </div>
            <p className="text-[11px] text-zinc-500">Replay window is inclusive and evaluated in UTC.</p>

            <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">Symbols</span>
                    <input
                        value={symbolsInput}
                        onChange={(event) => setSymbolsInput(event.target.value)}
                        placeholder="BTC/USDT, ETH/USDT"
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    />
                </label>
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">Timeframe</span>
                    <select
                        value={timeframe}
                        onChange={(event) => setTimeframe(event.target.value as BacktestTimeframe)}
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    >
                        <option value="1m">1m</option>
                        <option value="15m">15m</option>
                        <option value="1h">1h</option>
                        <option value="4h">4h</option>
                    </select>
                </label>
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">From</span>
                    <input
                        type="date"
                        value={fromDate}
                        onChange={(event) => setFromDate(event.target.value)}
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    />
                </label>
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">To</span>
                    <input
                        type="date"
                        value={toDate}
                        onChange={(event) => setToDate(event.target.value)}
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    />
                </label>
            </div>

            <div className="grid grid-cols-1 md:grid-cols-4 gap-3">
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">Initial Capital (USD)</span>
                    <input
                        type="number"
                        min={1}
                        value={initialCapital}
                        onChange={(event) => setInitialCapital(Number(event.target.value))}
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    />
                </label>
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">Slippage (bps)</span>
                    <input
                        type="number"
                        min={0}
                        value={slippageBps}
                        onChange={(event) => setSlippageBps(Number(event.target.value))}
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    />
                </label>
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">Fee (bps)</span>
                    <input
                        type="number"
                        min={0}
                        value={feeBps}
                        onChange={(event) => setFeeBps(Number(event.target.value))}
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    />
                </label>
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">Partial Fill %</span>
                    <input
                        type="number"
                        min={1}
                        max={100}
                        value={Math.round(partialFillPct * 100)}
                        onChange={(event) => setPartialFillPct(Math.max(0.01, Math.min(1, Number(event.target.value) / 100)))}
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    />
                </label>
            </div>

            <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">Signal Fill Timing</span>
                    <select
                        value={fillOnNextBar ? 'next_open' : 'same_close'}
                        onChange={(event) => setFillOnNextBar(event.target.value === 'next_open')}
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    >
                        <option value="next_open">Next bar open</option>
                        <option value="same_close">Same bar close</option>
                    </select>
                </label>
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">Intra-candle Conflict</span>
                    <select
                        value={intraCandlePolicy}
                        onChange={(event) => setIntraCandlePolicy(event.target.value as BacktestIntraCandlePolicy)}
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    >
                        <option value="ohlc_path">OHLC path</option>
                        <option value="stop_loss_first">Stop-loss first</option>
                        <option value="take_profit_first">Take-profit first</option>
                    </select>
                </label>
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">Trigger Resolution</span>
                    <select
                        value={triggerTimeframe}
                        onChange={(event) => setTriggerTimeframe(event.target.value as BacktestTriggerTimeframe)}
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    >
                        <option value="1m">1m trigger candles</option>
                        <option value="off">Base timeframe only</option>
                    </select>
                </label>
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">End-of-Window Position Handling</span>
                    <select
                        value={forceCloseAtWindowEnd ? 'force_close' : 'open_at_end'}
                        onChange={(event) => setForceCloseAtWindowEnd(event.target.value === 'force_close')}
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    >
                        <option value="open_at_end">Mark as OPEN_AT_END (Default)</option>
                        <option value="force_close">Force close at last candle</option>
                    </select>
                </label>
                <div className="rounded-lg border border-white/10 bg-zinc-900/70 px-3 py-2">
                    <p className="text-[10px] uppercase tracking-wider text-zinc-500">Replay Semantics</p>
                    <p className="text-[11px] text-zinc-300 mt-1">
                        No trades occur before <span className="font-semibold">{fromDate}</span>. Warm-up candles are still loaded before the replay window.
                    </p>
                </div>
            </div>

            <div className="grid grid-cols-1 md:grid-cols-2 gap-3 items-end">
                <label className="space-y-1">
                    <span className="text-[10px] uppercase tracking-wider text-zinc-400">Historical Data Type</span>
                    <select
                        value={sourceType}
                        onChange={(event) => {
                            setSourceType(event.target.value as SourceType);
                            if (event.target.value === 'kraken') {
                                setSourcePayload({ exchange: 'kraken' });
                                setSourceName('Kraken historical API');
                            } else {
                                setSourcePayload(null);
                                setSourceName('');
                            }
                        }}
                        className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                    >
                        <option value="csv">CSV</option>
                        <option value="json">JSON</option>
                        <option value="replay">Replay JSON</option>
                        <option value="kraken">Kraken Historical API</option>
                    </select>
                </label>
                {sourceType === 'kraken' ? (
                    <label className="space-y-1">
                        <span className="text-[10px] uppercase tracking-wider text-zinc-400">Kraken Warm-up Lookback Candles</span>
                        <input
                            type="number"
                            min={100}
                            value={krakenLookbackCandles}
                            onChange={(event) => setKrakenLookbackCandles(Math.max(100, Number(event.target.value || 0)))}
                            className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-white focus:outline-none focus:border-emerald-400/50"
                        />
                    </label>
                ) : (
                    <label className="space-y-1">
                        <span className="text-[10px] uppercase tracking-wider text-zinc-400">Upload Historical File</span>
                        <input
                            type="file"
                            accept={sourceType === 'csv' ? '.csv,text/csv' : '.json,application/json'}
                            onChange={async (event) => {
                                try {
                                    const file = event.target.files?.[0];
                                    if (!file) return;
                                    await readFile(file);
                                } catch (uploadError: any) {
                                    setError(uploadError.message || 'Failed to read file');
                                }
                            }}
                            className="w-full rounded-lg border border-white/10 bg-zinc-900 px-3 py-2 text-xs text-zinc-300 focus:outline-none focus:border-emerald-400/50"
                        />
                    </label>
                )}
            </div>

            <div className="text-[11px] text-zinc-500">
                Uploaded source: <span className="text-zinc-300">{sourceName || 'none'}</span>
            </div>

            {error && (
                <div className="rounded-lg border border-red-500/30 bg-red-500/10 px-3 py-2 text-xs text-red-300">
                    {error}
                </div>
            )}

            <button
                onClick={() => { void handleRun(); }}
                disabled={running}
                className={`w-full rounded-xl px-4 py-2 text-xs font-black uppercase tracking-wider transition-colors ${running
                    ? 'bg-zinc-800 text-zinc-500 cursor-not-allowed'
                    : 'bg-emerald-400 text-black hover:bg-emerald-300'
                    }`}
            >
                {running ? 'Running Backtest...' : 'Run Backtest'}
            </button>
        </div>
    );
};
