/**
 * Monte Carlo Simulator Component
 * Simulates portfolio performance using Monte Carlo method
 * with probability distributions and VaR calculations
 */

import React, { useState, useMemo, useCallback } from 'react';
import {
  ChartBarIcon,
  PlayIcon,
  ArrowPathIcon,
  InformationCircleIcon,
  ExclamationTriangleIcon,
} from '@heroicons/react/24/solid';

interface MonteCarloSimulatorProps {
  portfolioId: string;
  currentValue: number;
  annualReturn?: number;
  volatility?: number;
  compact?: boolean;
}

interface SimulationResult {
  paths: number[][];
  finalValues: number[];
  percentiles: Record<string, number>;
  var95: number;
  var99: number;
  cvar95: number;
  expectedValue: number;
  probabilityOfLoss: number;
  probabilityOfTarget: number;
  medianValue: number;
}

interface ConfidenceInterval {
  level: string;
  lower: number;
  upper: number;
  color: string;
}

const TIME_HORIZONS = [
  { value: 30, label: '1 Mes' },
  { value: 90, label: '3 Meses' },
  { value: 180, label: '6 Meses' },
  { value: 365, label: '1 Año' },
  { value: 730, label: '2 Años' },
  { value: 1825, label: '5 Años' },
];

const formatCurrency = (value: number): string => {
  return `$${value.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 0 })}`;
};

const formatPercent = (value: number): string => {
  return `${value.toFixed(1)}%`;
};

export const MonteCarloSimulator: React.FC<MonteCarloSimulatorProps> = ({
  portfolioId,
  currentValue,
  annualReturn = 0.12,
  volatility = 0.25,
  compact = false,
}) => {
  const [numSimulations, setNumSimulations] = useState(5000);
  const [timeHorizon, setTimeHorizon] = useState(365);
  const [targetReturn, setTargetReturn] = useState(10);
  const [isSimulating, setIsSimulating] = useState(false);
  const [result, setResult] = useState<SimulationResult | null>(null);
  const [showAdvanced, setShowAdvanced] = useState(false);

  // Custom return and volatility overrides
  const [customReturn, setCustomReturn] = useState<string>(String(annualReturn * 100));
  const [customVolatility, setCustomVolatility] = useState<string>(String(volatility * 100));

  // Run Monte Carlo simulation
  const runSimulation = useCallback(() => {
    setIsSimulating(true);

    // Use requestAnimationFrame to prevent UI blocking
    requestAnimationFrame(() => {
      const usedReturn = parseFloat(customReturn) / 100;
      const usedVolatility = parseFloat(customVolatility) / 100;

      // Daily parameters
      const tradingDays = timeHorizon;
      const dailyReturn = usedReturn / 252;
      const dailyVolatility = usedVolatility / Math.sqrt(252);

      const paths: number[][] = [];
      const finalValues: number[] = [];

      // Run simulations
      for (let sim = 0; sim < numSimulations; sim++) {
        const path: number[] = [currentValue];
        let value = currentValue;

        for (let day = 1; day <= tradingDays; day++) {
          // Generate random normal using Box-Muller transform
          const u1 = Math.random();
          const u2 = Math.random();
          const z = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);

          // Geometric Brownian Motion
          const drift = (dailyReturn - 0.5 * dailyVolatility * dailyVolatility);
          const diffusion = dailyVolatility * z;
          value = value * Math.exp(drift + diffusion);

          // Store path points at intervals (for visualization)
          if (sim < 100 && day % Math.max(1, Math.floor(tradingDays / 50)) === 0) {
            path.push(value);
          }
        }

        if (sim < 100) {
          paths.push(path);
        }
        finalValues.push(value);
      }

      // Sort final values for percentile calculations
      finalValues.sort((a, b) => a - b);

      // Calculate percentiles
      const getPercentile = (p: number): number => {
        const index = Math.floor((p / 100) * finalValues.length);
        return finalValues[Math.min(index, finalValues.length - 1)];
      };

      const percentiles: Record<string, number> = {
        p5: getPercentile(5),
        p10: getPercentile(10),
        p25: getPercentile(25),
        p50: getPercentile(50),
        p75: getPercentile(75),
        p90: getPercentile(90),
        p95: getPercentile(95),
      };

      // Calculate VaR (Value at Risk)
      const var95 = currentValue - getPercentile(5);
      const var99 = currentValue - getPercentile(1);

      // Calculate CVaR (Conditional VaR / Expected Shortfall)
      const var95Index = Math.floor(0.05 * finalValues.length);
      const worstValues = finalValues.slice(0, var95Index);
      const cvar95 = currentValue - (worstValues.reduce((a, b) => a + b, 0) / worstValues.length);

      // Calculate statistics
      const expectedValue = finalValues.reduce((a, b) => a + b, 0) / finalValues.length;
      const probabilityOfLoss = (finalValues.filter(v => v < currentValue).length / finalValues.length) * 100;
      const targetValue = currentValue * (1 + targetReturn / 100);
      const probabilityOfTarget = (finalValues.filter(v => v >= targetValue).length / finalValues.length) * 100;

      setResult({
        paths,
        finalValues,
        percentiles,
        var95,
        var99,
        cvar95,
        expectedValue,
        probabilityOfLoss,
        probabilityOfTarget,
        medianValue: percentiles.p50,
      });

      setIsSimulating(false);
    });
  }, [currentValue, numSimulations, timeHorizon, targetReturn, customReturn, customVolatility]);

  // Confidence intervals for display
  const confidenceIntervals: ConfidenceInterval[] = useMemo(() => {
    if (!result) return [];
    return [
      { level: '90%', lower: result.percentiles.p5, upper: result.percentiles.p95, color: 'bg-blue-100 dark:bg-blue-900/30' },
      { level: '50%', lower: result.percentiles.p25, upper: result.percentiles.p75, color: 'bg-blue-200 dark:bg-blue-800/40' },
    ];
  }, [result]);

  // Distribution chart data
  const distributionData = useMemo(() => {
    if (!result) return null;

    const min = result.finalValues[0];
    const max = result.finalValues[result.finalValues.length - 1];
    const range = max - min;
    const bucketCount = 40;
    const bucketSize = range / bucketCount;

    const buckets = new Array(bucketCount).fill(0);
    result.finalValues.forEach(value => {
      const bucketIndex = Math.min(Math.floor((value - min) / bucketSize), bucketCount - 1);
      buckets[bucketIndex]++;
    });

    const maxCount = Math.max(...buckets);
    return {
      buckets,
      maxCount,
      min,
      max,
      bucketSize,
    };
  }, [result]);

  if (compact) {
    return (
      <div className="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6">
        <div className="flex items-center justify-between mb-4">
          <div className="flex items-center gap-3">
            <div className="p-2 bg-indigo-100 dark:bg-indigo-900/30 rounded-lg">
              <ChartBarIcon className="w-5 h-5 text-indigo-600" />
            </div>
            <h3 className="font-bold text-gray-900 dark:text-white">Monte Carlo</h3>
          </div>
          <button
            onClick={runSimulation}
            disabled={isSimulating}
            className="px-3 py-1.5 bg-indigo-600 hover:bg-indigo-700 disabled:bg-indigo-400 text-white text-sm font-medium rounded-lg transition-colors flex items-center gap-1"
          >
            {isSimulating ? (
              <ArrowPathIcon className="w-4 h-4 animate-spin" />
            ) : (
              <PlayIcon className="w-4 h-4" />
            )}
            Simular
          </button>
        </div>

        {result ? (
          <div className="grid grid-cols-2 gap-3">
            <div className="p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg text-center">
              <p className="text-xs text-gray-500 dark:text-gray-400">VaR 95%</p>
              <p className="text-lg font-bold text-red-500">
                {formatCurrency(result.var95)}
              </p>
            </div>
            <div className="p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg text-center">
              <p className="text-xs text-gray-500 dark:text-gray-400">Esperado</p>
              <p className={`text-lg font-bold ${result.expectedValue >= currentValue ? 'text-green-500' : 'text-red-500'}`}>
                {formatCurrency(result.expectedValue)}
              </p>
            </div>
            <div className="p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg text-center">
              <p className="text-xs text-gray-500 dark:text-gray-400">Prob. Perdida</p>
              <p className="text-lg font-bold text-orange-500">
                {formatPercent(result.probabilityOfLoss)}
              </p>
            </div>
            <div className="p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg text-center">
              <p className="text-xs text-gray-500 dark:text-gray-400">Prob. +{targetReturn}%</p>
              <p className="text-lg font-bold text-green-500">
                {formatPercent(result.probabilityOfTarget)}
              </p>
            </div>
          </div>
        ) : (
          <div className="text-center py-6">
            <p className="text-sm text-gray-500 dark:text-gray-400">
              Ejecuta una simulacion para ver resultados
            </p>
          </div>
        )}
      </div>
    );
  }

  return (
    <div className="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6">
      {/* Header */}
      <div className="flex items-center justify-between mb-6">
        <div className="flex items-center gap-3">
          <div className="p-2 bg-indigo-100 dark:bg-indigo-900/30 rounded-lg">
            <ChartBarIcon className="w-6 h-6 text-indigo-600" />
          </div>
          <div>
            <h3 className="font-bold text-gray-900 dark:text-white">Simulador Monte Carlo</h3>
            <p className="text-sm text-gray-500 dark:text-gray-400">
              Analisis de escenarios probabilisticos
            </p>
          </div>
        </div>
      </div>

      {/* Configuration */}
      <div className="grid md:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
        {/* Number of Simulations */}
        <div>
          <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
            Simulaciones
          </label>
          <select
            value={numSimulations}
            onChange={(e) => setNumSimulations(Number(e.target.value))}
            className="w-full px-3 py-2 bg-gray-50 dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-indigo-500 text-gray-900 dark:text-white"
          >
            <option value={1000}>1,000</option>
            <option value={5000}>5,000</option>
            <option value={10000}>10,000</option>
          </select>
        </div>

        {/* Time Horizon */}
        <div>
          <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
            Horizonte Temporal
          </label>
          <select
            value={timeHorizon}
            onChange={(e) => setTimeHorizon(Number(e.target.value))}
            className="w-full px-3 py-2 bg-gray-50 dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-indigo-500 text-gray-900 dark:text-white"
          >
            {TIME_HORIZONS.map((h) => (
              <option key={h.value} value={h.value}>{h.label}</option>
            ))}
          </select>
        </div>

        {/* Target Return */}
        <div>
          <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
            Retorno Objetivo (%)
          </label>
          <input
            type="number"
            value={targetReturn}
            onChange={(e) => setTargetReturn(Number(e.target.value))}
            min={-50}
            max={200}
            className="w-full px-3 py-2 bg-gray-50 dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-indigo-500 text-gray-900 dark:text-white"
          />
        </div>

        {/* Run Button */}
        <div className="flex items-end">
          <button
            onClick={runSimulation}
            disabled={isSimulating}
            className="w-full px-4 py-2 bg-indigo-600 hover:bg-indigo-700 disabled:bg-indigo-400 text-white font-medium rounded-lg transition-colors flex items-center justify-center gap-2"
          >
            {isSimulating ? (
              <>
                <ArrowPathIcon className="w-5 h-5 animate-spin" />
                Simulando...
              </>
            ) : (
              <>
                <PlayIcon className="w-5 h-5" />
                Ejecutar
              </>
            )}
          </button>
        </div>
      </div>

      {/* Advanced Settings Toggle */}
      <button
        onClick={() => setShowAdvanced(!showAdvanced)}
        className="text-sm text-indigo-600 dark:text-indigo-400 hover:text-indigo-700 mb-4"
      >
        {showAdvanced ? 'Ocultar parametros avanzados' : 'Mostrar parametros avanzados'}
      </button>

      {/* Advanced Settings */}
      {showAdvanced && (
        <div className="grid md:grid-cols-2 gap-4 mb-6 p-4 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
          <div>
            <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
              Retorno Anual Esperado (%)
            </label>
            <input
              type="number"
              value={customReturn}
              onChange={(e) => setCustomReturn(e.target.value)}
              step="0.5"
              className="w-full px-3 py-2 bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-indigo-500 text-gray-900 dark:text-white"
            />
          </div>
          <div>
            <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
              Volatilidad Anual (%)
            </label>
            <input
              type="number"
              value={customVolatility}
              onChange={(e) => setCustomVolatility(e.target.value)}
              step="0.5"
              className="w-full px-3 py-2 bg-white dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-lg focus:ring-2 focus:ring-indigo-500 text-gray-900 dark:text-white"
            />
          </div>
        </div>
      )}

      {/* Results */}
      {result && (
        <>
          {/* Distribution Chart */}
          {distributionData && (
            <div className="mb-6">
              <h4 className="text-sm font-semibold text-gray-700 dark:text-gray-300 mb-3">
                Distribucion de Valores Finales
              </h4>
              <div className="relative h-40 bg-gray-50 dark:bg-gray-700/50 rounded-lg p-4">
                {/* Chart bars */}
                <div className="flex items-end h-full gap-px">
                  {distributionData.buckets.map((count, index) => {
                    const height = (count / distributionData.maxCount) * 100;
                    const value = distributionData.min + (index * distributionData.bucketSize);
                    const isLoss = value < currentValue;
                    const isTarget = value >= currentValue * (1 + targetReturn / 100);

                    return (
                      <div
                        key={index}
                        className={`flex-1 rounded-t transition-all ${
                          isLoss
                            ? 'bg-red-400 dark:bg-red-500'
                            : isTarget
                            ? 'bg-green-400 dark:bg-green-500'
                            : 'bg-indigo-400 dark:bg-indigo-500'
                        }`}
                        style={{ height: `${Math.max(1, height)}%` }}
                        title={`${formatCurrency(value)}: ${count} simulaciones`}
                      />
                    );
                  })}
                </div>

                {/* Current value marker */}
                <div
                  className="absolute bottom-0 w-0.5 h-full bg-gray-900 dark:bg-white"
                  style={{
                    left: `${((currentValue - distributionData.min) / (distributionData.max - distributionData.min)) * 100}%`,
                  }}
                />
              </div>

              {/* Legend */}
              <div className="flex justify-center gap-6 mt-3 text-xs">
                <div className="flex items-center gap-1">
                  <div className="w-3 h-3 bg-red-400 rounded" />
                  <span className="text-gray-600 dark:text-gray-400">Perdida</span>
                </div>
                <div className="flex items-center gap-1">
                  <div className="w-3 h-3 bg-indigo-400 rounded" />
                  <span className="text-gray-600 dark:text-gray-400">Ganancia</span>
                </div>
                <div className="flex items-center gap-1">
                  <div className="w-3 h-3 bg-green-400 rounded" />
                  <span className="text-gray-600 dark:text-gray-400">Objetivo +{targetReturn}%</span>
                </div>
              </div>
            </div>
          )}

          {/* VaR Display */}
          <div className="grid md:grid-cols-3 gap-4 mb-6">
            <div className="p-4 bg-red-50 dark:bg-red-900/20 rounded-lg border border-red-200 dark:border-red-800">
              <div className="flex items-center gap-2 mb-2">
                <ExclamationTriangleIcon className="w-5 h-5 text-red-500" />
                <span className="text-sm font-medium text-red-700 dark:text-red-400">VaR 95%</span>
              </div>
              <p className="text-2xl font-bold text-red-600">{formatCurrency(result.var95)}</p>
              <p className="text-xs text-red-600 dark:text-red-400 mt-1">
                Perdida maxima con 95% de confianza
              </p>
            </div>

            <div className="p-4 bg-orange-50 dark:bg-orange-900/20 rounded-lg border border-orange-200 dark:border-orange-800">
              <div className="flex items-center gap-2 mb-2">
                <ExclamationTriangleIcon className="w-5 h-5 text-orange-500" />
                <span className="text-sm font-medium text-orange-700 dark:text-orange-400">CVaR 95%</span>
              </div>
              <p className="text-2xl font-bold text-orange-600">{formatCurrency(result.cvar95)}</p>
              <p className="text-xs text-orange-600 dark:text-orange-400 mt-1">
                Perdida esperada en el peor 5%
              </p>
            </div>

            <div className="p-4 bg-purple-50 dark:bg-purple-900/20 rounded-lg border border-purple-200 dark:border-purple-800">
              <div className="flex items-center gap-2 mb-2">
                <ExclamationTriangleIcon className="w-5 h-5 text-purple-500" />
                <span className="text-sm font-medium text-purple-700 dark:text-purple-400">VaR 99%</span>
              </div>
              <p className="text-2xl font-bold text-purple-600">{formatCurrency(result.var99)}</p>
              <p className="text-xs text-purple-600 dark:text-purple-400 mt-1">
                Perdida maxima con 99% de confianza
              </p>
            </div>
          </div>

          {/* Confidence Intervals */}
          <div className="mb-6">
            <h4 className="text-sm font-semibold text-gray-700 dark:text-gray-300 mb-3">
              Intervalos de Confianza
            </h4>
            <div className="space-y-3">
              {confidenceIntervals.map((interval) => (
                <div key={interval.level} className={`p-3 rounded-lg ${interval.color}`}>
                  <div className="flex items-center justify-between">
                    <span className="text-sm font-medium text-gray-700 dark:text-gray-300">
                      Intervalo {interval.level}
                    </span>
                    <span className="text-sm text-gray-600 dark:text-gray-400">
                      {formatCurrency(interval.lower)} - {formatCurrency(interval.upper)}
                    </span>
                  </div>
                </div>
              ))}
            </div>
          </div>

          {/* Summary Statistics */}
          <div className="grid md:grid-cols-2 lg:grid-cols-4 gap-4">
            <div className="p-4 bg-gray-50 dark:bg-gray-700/50 rounded-lg text-center">
              <p className="text-xs text-gray-500 dark:text-gray-400">Valor Esperado</p>
              <p className={`text-xl font-bold ${result.expectedValue >= currentValue ? 'text-green-500' : 'text-red-500'}`}>
                {formatCurrency(result.expectedValue)}
              </p>
              <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
                ({((result.expectedValue / currentValue - 1) * 100).toFixed(1)}%)
              </p>
            </div>

            <div className="p-4 bg-gray-50 dark:bg-gray-700/50 rounded-lg text-center">
              <p className="text-xs text-gray-500 dark:text-gray-400">Valor Mediano</p>
              <p className={`text-xl font-bold ${result.medianValue >= currentValue ? 'text-green-500' : 'text-red-500'}`}>
                {formatCurrency(result.medianValue)}
              </p>
              <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
                ({((result.medianValue / currentValue - 1) * 100).toFixed(1)}%)
              </p>
            </div>

            <div className="p-4 bg-gray-50 dark:bg-gray-700/50 rounded-lg text-center">
              <p className="text-xs text-gray-500 dark:text-gray-400">Prob. de Perdida</p>
              <p className="text-xl font-bold text-orange-500">
                {formatPercent(result.probabilityOfLoss)}
              </p>
              <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
                Valor {'<'} {formatCurrency(currentValue)}
              </p>
            </div>

            <div className="p-4 bg-gray-50 dark:bg-gray-700/50 rounded-lg text-center">
              <p className="text-xs text-gray-500 dark:text-gray-400">Prob. Objetivo</p>
              <p className="text-xl font-bold text-green-500">
                {formatPercent(result.probabilityOfTarget)}
              </p>
              <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
                Retorno {'>='} +{targetReturn}%
              </p>
            </div>
          </div>

          {/* Info Footer */}
          <div className="mt-6 pt-4 border-t border-gray-200 dark:border-gray-700">
            <div className="flex items-start gap-2">
              <InformationCircleIcon className="w-5 h-5 text-gray-400 flex-shrink-0" />
              <p className="text-xs text-gray-500 dark:text-gray-400">
                Simulacion basada en {numSimulations.toLocaleString()} escenarios usando movimiento browniano
                geometrico con retorno anualizado de {customReturn}% y volatilidad de {customVolatility}%.
                Los resultados son estimaciones y no garantizan rendimientos futuros.
              </p>
            </div>
          </div>
        </>
      )}

      {/* Empty State */}
      {!result && !isSimulating && (
        <div className="text-center py-12 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
          <ChartBarIcon className="w-12 h-12 text-gray-400 mx-auto mb-3" />
          <h4 className="font-medium text-gray-900 dark:text-white mb-1">
            Configura y Ejecuta la Simulacion
          </h4>
          <p className="text-sm text-gray-500 dark:text-gray-400 max-w-md mx-auto">
            El simulador Monte Carlo genera miles de escenarios posibles para estimar
            el rango de valores futuros de tu portfolio y el riesgo asociado.
          </p>
        </div>
      )}
    </div>
  );
};

export default MonteCarloSimulator;
