import React, { useState, useMemo, useCallback } from 'react';
import { ChartData, SliderConfig } from '../types';
import { Play, Pause, RotateCcw, Eye, EyeOff, Sliders, Info } from 'lucide-react';

interface Props {
  data: ChartData;
  theme: 'light' | 'dark';
}

// Default colors palette
const DEFAULT_COLORS = [
  '#0ea5e9', // brand blue
  '#8b5cf6', // purple
  '#10b981', // emerald
  '#f59e0b', // amber
  '#ef4444', // red
  '#ec4899', // pink
  '#06b6d4', // cyan
  '#84cc16', // lime
];

const InteractiveChartPlayable: React.FC<Props> = ({ data, theme }) => {
  const isDark = theme === 'dark';
  const colors = data.colors || DEFAULT_COLORS;
  
  // State for interactive features
  const [sliderValues, setSliderValues] = useState<Record<string, number>>(() => {
    const initial: Record<string, number> = {};
    data.interactive?.sliderConfig?.forEach(config => {
      initial[config.id] = config.defaultValue;
    });
    return initial;
  });
  
  const [visibleDatasets, setVisibleDatasets] = useState<Set<string>>(() => {
    return new Set(data.data.map(d => d.label));
  });
  
  const [hoveredItem, setHoveredItem] = useState<number | null>(null);
  const [isAnimating, setIsAnimating] = useState(false);
  const [showControls, setShowControls] = useState(true);

  // Apply slider transformations to data
  const transformedData = useMemo(() => {
    if (!data.interactive?.enableSliders || !data.interactive.sliderConfig) {
      return data.data;
    }

    return data.data.map(item => {
      let newValue = item.value;
      
      data.interactive?.sliderConfig?.forEach(config => {
        const sliderValue = sliderValues[config.id] || config.defaultValue;
        
        // Apply transformation based on the affected variable
        if (config.affectsVariable === 'multiplier') {
          newValue = item.value * sliderValue;
        } else if (config.affectsVariable === 'offset') {
          newValue = item.value + sliderValue;
        } else if (config.affectsVariable === 'power') {
          newValue = Math.pow(item.value, sliderValue);
        }
      });
      
      return { ...item, value: newValue };
    });
  }, [data.data, sliderValues, data.interactive]);

  // Filter by visible datasets
  const visibleData = useMemo(() => {
    return transformedData.filter(item => visibleDatasets.has(item.label));
  }, [transformedData, visibleDatasets]);

  const maxValue = useMemo(() => {
    return Math.max(...visibleData.map(d => d.value), 1);
  }, [visibleData]);

  const handleSliderChange = useCallback((sliderId: string, value: number) => {
    setSliderValues(prev => ({ ...prev, [sliderId]: value }));
  }, []);

  const handleToggleDataset = useCallback((label: string) => {
    setVisibleDatasets(prev => {
      const next = new Set(prev);
      if (next.has(label)) {
        if (next.size > 1) next.delete(label);
      } else {
        next.add(label);
      }
      return next;
    });
  }, []);

  const handleReset = useCallback(() => {
    setSliderValues(() => {
      const initial: Record<string, number> = {};
      data.interactive?.sliderConfig?.forEach(config => {
        initial[config.id] = config.defaultValue;
      });
      return initial;
    });
    setVisibleDatasets(new Set(data.data.map(d => d.label)));
  }, [data]);

  const handleAnimate = useCallback(() => {
    if (!data.interactive?.sliderConfig?.[0]) return;
    
    setIsAnimating(true);
    const config = data.interactive.sliderConfig[0];
    const steps = 20;
    const stepSize = (config.max - config.min) / steps;
    let currentStep = 0;
    
    const interval = setInterval(() => {
      setSliderValues(prev => ({
        ...prev,
        [config.id]: config.min + (stepSize * currentStep)
      }));
      currentStep++;
      
      if (currentStep > steps) {
        clearInterval(interval);
        setIsAnimating(false);
      }
    }, 100);
  }, [data.interactive]);

  // Chart dimensions
  const chartWidth = 400;
  const chartHeight = 200;
  const barWidth = Math.min(50, (chartWidth - 80) / Math.max(visibleData.length, 1) - 10);

  const renderBarChart = () => (
    <svg viewBox={`0 0 ${chartWidth} ${chartHeight + 60}`} className="w-full h-auto">
      {/* Grid lines */}
      {[0, 0.25, 0.5, 0.75, 1].map((ratio, i) => (
        <g key={i}>
          <text
            x="30"
            y={chartHeight - (ratio * chartHeight) + 5}
            className={`text-[10px] ${isDark ? 'fill-gray-400' : 'fill-gray-500'}`}
            textAnchor="end"
          >
            {Math.round(maxValue * ratio)}
          </text>
          <line
            x1="40"
            y1={chartHeight - (ratio * chartHeight)}
            x2={chartWidth - 10}
            y2={chartHeight - (ratio * chartHeight)}
            className={isDark ? 'stroke-gray-700' : 'stroke-gray-200'}
            strokeDasharray="4,4"
          />
        </g>
      ))}
      
      {/* Bars with animation */}
      {visibleData.map((item, index) => {
        const barHeight = (item.value / maxValue) * chartHeight;
        const x = 50 + index * ((chartWidth - 60) / Math.max(visibleData.length, 1));
        const y = chartHeight - barHeight;
        const isHovered = hoveredItem === index;
        const originalIndex = data.data.findIndex(d => d.label === item.label);
        
        return (
          <g 
            key={item.label} 
            className="cursor-pointer"
            onMouseEnter={() => setHoveredItem(index)}
            onMouseLeave={() => setHoveredItem(null)}
          >
            {/* Bar */}
            <rect
              x={x}
              y={y}
              width={barWidth}
              height={barHeight}
              fill={colors[originalIndex % colors.length]}
              rx="4"
              className={`
                transition-all duration-300 ease-out
                ${isHovered ? 'opacity-100' : 'opacity-85'}
              `}
              style={{
                transform: isHovered ? 'scale(1.02)' : 'scale(1)',
                transformOrigin: `${x + barWidth/2}px ${chartHeight}px`
              }}
            />
            
            {/* Highlight glow on hover */}
            {isHovered && (
              <rect
                x={x - 2}
                y={y - 2}
                width={barWidth + 4}
                height={barHeight + 4}
                fill="none"
                stroke={colors[originalIndex % colors.length]}
                strokeWidth="2"
                rx="6"
                opacity="0.3"
              />
            )}
            
            {/* Value tooltip on hover */}
            {isHovered && (
              <g>
                <rect
                  x={x + barWidth/2 - 25}
                  y={y - 35}
                  width="50"
                  height="24"
                  rx="4"
                  className={isDark ? 'fill-gray-800' : 'fill-gray-900'}
                />
                <text
                  x={x + barWidth / 2}
                  y={y - 18}
                  textAnchor="middle"
                  className="text-[12px] font-bold fill-white"
                >
                  {item.value.toFixed(1)}
                </text>
              </g>
            )}
            
            {/* Label */}
            <text
              x={x + barWidth / 2}
              y={chartHeight + 18}
              textAnchor="middle"
              className={`text-[10px] ${isDark ? 'fill-gray-400' : 'fill-gray-600'} ${isHovered ? 'font-bold' : ''}`}
            >
              {item.label.length > 10 ? item.label.substring(0, 10) + '...' : item.label}
            </text>
          </g>
        );
      })}
    </svg>
  );

  const renderLineChart = () => {
    const points = visibleData.map((item, index) => {
      const x = 50 + index * ((chartWidth - 80) / (Math.max(visibleData.length, 1) - 1 || 1));
      const y = chartHeight - (item.value / maxValue) * chartHeight;
      return { x, y, ...item };
    });

    const pathD = points
      .map((p, i) => `${i === 0 ? 'M' : 'L'} ${p.x} ${p.y}`)
      .join(' ');

    const areaD = `${pathD} L ${points[points.length - 1]?.x || 0} ${chartHeight} L ${points[0]?.x || 0} ${chartHeight} Z`;

    return (
      <svg viewBox={`0 0 ${chartWidth} ${chartHeight + 60}`} className="w-full h-auto">
        {/* Grid */}
        {[0, 0.25, 0.5, 0.75, 1].map((ratio, i) => (
          <g key={i}>
            <text
              x="30"
              y={chartHeight - (ratio * chartHeight) + 5}
              className={`text-[10px] ${isDark ? 'fill-gray-400' : 'fill-gray-500'}`}
              textAnchor="end"
            >
              {Math.round(maxValue * ratio)}
            </text>
            <line
              x1="40"
              y1={chartHeight - (ratio * chartHeight)}
              x2={chartWidth - 10}
              y2={chartHeight - (ratio * chartHeight)}
              className={isDark ? 'stroke-gray-700' : 'stroke-gray-200'}
              strokeDasharray="4,4"
            />
          </g>
        ))}

        {/* Area fill */}
        <path
          d={areaD}
          fill={colors[0]}
          fillOpacity="0.15"
          className="transition-all duration-300"
        />

        {/* Line */}
        <path
          d={pathD}
          fill="none"
          stroke={colors[0]}
          strokeWidth="3"
          strokeLinecap="round"
          strokeLinejoin="round"
          className="transition-all duration-300"
        />

        {/* Interactive points */}
        {points.map((point, index) => (
          <g 
            key={index}
            className="cursor-pointer"
            onMouseEnter={() => setHoveredItem(index)}
            onMouseLeave={() => setHoveredItem(null)}
          >
            {/* Larger hit area */}
            <circle
              cx={point.x}
              cy={point.y}
              r="15"
              fill="transparent"
            />
            
            {/* Visible point */}
            <circle
              cx={point.x}
              cy={point.y}
              r={hoveredItem === index ? 8 : 5}
              fill={colors[0]}
              className="transition-all duration-200"
            />
            <circle
              cx={point.x}
              cy={point.y}
              r={hoveredItem === index ? 4 : 2}
              fill={isDark ? '#1e293b' : 'white'}
            />
            
            {/* Tooltip */}
            {hoveredItem === index && (
              <g>
                <rect
                  x={point.x - 30}
                  y={point.y - 40}
                  width="60"
                  height="28"
                  rx="4"
                  className={isDark ? 'fill-gray-800' : 'fill-gray-900'}
                />
                <text
                  x={point.x}
                  y={point.y - 22}
                  textAnchor="middle"
                  className="text-[11px] font-bold fill-white"
                >
                  {point.value.toFixed(1)}
                </text>
              </g>
            )}
            
            {/* X-axis label */}
            <text
              x={point.x}
              y={chartHeight + 18}
              textAnchor="middle"
              className={`text-[10px] ${isDark ? 'fill-gray-400' : 'fill-gray-600'}`}
            >
              {point.label.length > 8 ? point.label.substring(0, 8) + '..' : point.label}
            </text>
          </g>
        ))}
      </svg>
    );
  };

  return (
    <div className="space-y-4">
      {/* Interactive Controls Header */}
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-2">
          <Sliders size={16} className="text-brand-500" />
          <span className="text-xs font-bold uppercase tracking-wider text-gray-500 dark:text-gray-400">
            Interactive Chart
          </span>
        </div>
        
        <div className="flex items-center gap-2">
          {data.interactive?.enableSliders && (
            <button
              onClick={handleAnimate}
              disabled={isAnimating}
              className={`
                flex items-center gap-1 px-2 py-1 rounded-lg text-xs font-medium transition-colors
                ${isAnimating 
                  ? 'bg-brand-100 dark:bg-brand-900/30 text-brand-600 dark:text-brand-400' 
                  : 'bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700'
                }
              `}
            >
              {isAnimating ? <Pause size={12} /> : <Play size={12} />}
              {isAnimating ? 'Playing' : 'Animate'}
            </button>
          )}
          
          <button
            onClick={handleReset}
            className="flex items-center gap-1 px-2 py-1 rounded-lg text-xs font-medium bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors"
          >
            <RotateCcw size={12} />
            Reset
          </button>
          
          <button
            onClick={() => setShowControls(!showControls)}
            className={`
              p-1.5 rounded-lg transition-colors
              ${showControls 
                ? 'bg-brand-100 dark:bg-brand-900/30 text-brand-600 dark:text-brand-400' 
                : 'bg-gray-100 dark:bg-gray-800 text-gray-500'
              }
            `}
          >
            {showControls ? <Eye size={14} /> : <EyeOff size={14} />}
          </button>
        </div>
      </div>

      {/* Title */}
      {data.title && (
        <h4 className="text-center text-sm font-semibold text-gray-700 dark:text-gray-300">
          {data.title}
        </h4>
      )}

      {/* Chart */}
      <div className="relative bg-white dark:bg-gray-900 rounded-xl p-4">
        {data.type === 'line' || data.type === 'area' ? renderLineChart() : renderBarChart()}
      </div>

      {/* Interactive Controls */}
      {showControls && (
        <div className="space-y-4 p-4 bg-gray-50 dark:bg-gray-800/50 rounded-xl border border-gray-200 dark:border-gray-700">
          
          {/* Sliders */}
          {data.interactive?.enableSliders && data.interactive.sliderConfig?.map((config) => (
            <div key={config.id} className="space-y-2">
              <div className="flex items-center justify-between">
                <label className="text-xs font-medium text-gray-700 dark:text-gray-300">
                  {config.label}
                </label>
                <span className="text-sm font-mono font-bold text-brand-600 dark:text-brand-400">
                  {sliderValues[config.id]?.toFixed(2) || config.defaultValue.toFixed(2)}
                </span>
              </div>
              <input
                type="range"
                min={config.min}
                max={config.max}
                step={config.step}
                value={sliderValues[config.id] || config.defaultValue}
                onChange={(e) => handleSliderChange(config.id, parseFloat(e.target.value))}
                className="w-full h-2 bg-gray-200 dark:bg-gray-700 rounded-lg appearance-none cursor-pointer accent-brand-500"
              />
              <div className="flex justify-between text-[10px] text-gray-400">
                <span>{config.min}</span>
                <span>{config.max}</span>
              </div>
            </div>
          ))}

          {/* Dataset Toggles */}
          {data.interactive?.enableToggles && (
            <div className="space-y-2">
              <label className="text-xs font-medium text-gray-700 dark:text-gray-300">
                Toggle Datasets
              </label>
              <div className="flex flex-wrap gap-2">
                {data.data.map((item, idx) => (
                  <button
                    key={item.label}
                    onClick={() => handleToggleDataset(item.label)}
                    className={`
                      flex items-center gap-2 px-3 py-1.5 rounded-lg text-xs font-medium transition-all
                      ${visibleDatasets.has(item.label)
                        ? 'bg-white dark:bg-gray-700 shadow-sm border border-gray-200 dark:border-gray-600'
                        : 'bg-gray-100 dark:bg-gray-800 opacity-50'
                      }
                    `}
                  >
                    <span
                      className="w-3 h-3 rounded-full"
                      style={{ backgroundColor: colors[idx % colors.length] }}
                    />
                    <span className={visibleDatasets.has(item.label) ? '' : 'line-through'}>
                      {item.label}
                    </span>
                  </button>
                ))}
              </div>
            </div>
          )}

          {/* Info tooltip */}
          <div className="flex items-start gap-2 p-3 rounded-lg bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300">
            <Info size={14} className="flex-shrink-0 mt-0.5" />
            <p className="text-xs">
              <span className="font-medium">Tip:</span> Hover over data points for details. 
              {data.interactive?.enableSliders && ' Use the slider to see how changes affect the visualization.'}
              {data.interactive?.enableToggles && ' Toggle datasets on/off to compare.'}
            </p>
          </div>
        </div>
      )}

      {/* Axis Labels */}
      {(data.xAxis || data.yAxis) && (
        <div className="flex justify-between text-xs text-gray-500 dark:text-gray-400 italic">
          {data.yAxis && <span>↑ {data.yAxis}</span>}
          {data.xAxis && <span>{data.xAxis} →</span>}
        </div>
      )}
    </div>
  );
};

export default InteractiveChartPlayable;
