import React, { useState, useEffect } from 'react';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';
import { Loader2, Calendar, TrendingUp, Database, Clock } from 'lucide-react';
import api from '../services/api';

interface TimelineData {
  year: number;
  [key: string]: number;
}

interface AlgorithmTimeline {
  algorithm: string;
  name: string;
  category: string;
  data: { year: number; count: number }[];
}

interface CacheStats {
  cached: number;
  fetched: number;
}

interface ProgressState {
  current: number;
  total: number;
  currentAlgorithm: string;
}

const Timeline: React.FC = () => {
  const [timelineData, setTimelineData] = useState<TimelineData[]>([]);
  const [algorithms, setAlgorithms] = useState<AlgorithmTimeline[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [selectedAlgorithms, setSelectedAlgorithms] = useState<string[]>([]);
  const [yearRange, setYearRange] = useState({ start: 2015, end: 2024 });
  const [cacheStats, setCacheStats] = useState<CacheStats | null>(null);
  const [progress, setProgress] = useState<ProgressState | null>(null);

  useEffect(() => {
    fetchTimelineData();
  }, [yearRange]);

  const fetchTimelineData = async () => {
    try {
      setLoading(true);
      setError(null);
      setProgress(null);
      setCacheStats(null);
      
      // Use Server-Sent Events for real-time progress
      const eventSource = new EventSource(`/api/search/timeline-stream?startYear=${yearRange.start}&endYear=${yearRange.end}`);
      
      eventSource.onmessage = (event) => {
        const data = JSON.parse(event.data);
        
        switch (data.type) {
          case 'init':
            setProgress({
              current: 0,
              total: data.totalOperations,
              currentAlgorithm: data.message
            });
            setCacheStats({
              cached: data.cachedResults,
              fetched: data.fetchedResults
            });
            break;
            
          case 'algorithm_start':
            setProgress({
              current: data.completed,
              total: data.total,
              currentAlgorithm: `Processing ${data.algorithm}...`
            });
            break;
            
          case 'year_complete':
            setProgress({
              current: data.completed,
              total: data.total,
              currentAlgorithm: `${data.algorithm} (${data.year}): ${data.count} papers`
            });
            break;
            
          case 'algorithm_complete':
            setProgress({
              current: data.completed,
              total: data.total,
              currentAlgorithm: `Completed ${data.algorithm}`
            });
            break;
            
          case 'cache_saved':
            setProgress(prev => prev ? {
              ...prev,
              currentAlgorithm: data.message
            } : null);
            break;
            
          case 'complete':
            setTimelineData(data.timelineData);
            setAlgorithms(data.algorithms);
            setCacheStats(data.cacheStats);
            
            // Auto-select top 5 algorithms if none selected
            if (selectedAlgorithms.length === 0) {
              const topAlgorithms = data.algorithms
                .sort((a: AlgorithmTimeline, b: AlgorithmTimeline) => {
                  const aTotal = a.data.reduce((sum, item) => sum + item.count, 0);
                  const bTotal = b.data.reduce((sum, item) => sum + item.count, 0);
                  return bTotal - aTotal;
                })
                .slice(0, 5)
                .map((algo: AlgorithmTimeline) => algo.algorithm);
              setSelectedAlgorithms(topAlgorithms);
            }
            
            setLoading(false);
            setProgress(null);
            eventSource.close();
            break;
            
          case 'error':
            setError(`Failed to load timeline data: ${data.error}`);
            setLoading(false);
            setProgress(null);
            eventSource.close();
            break;
        }
      };
      
      eventSource.onerror = () => {
        setError('Connection lost while loading timeline data');
        setLoading(false);
        setProgress(null);
        eventSource.close();
      };
      
    } catch (err) {
      setError('Failed to start timeline data loading');
      setLoading(false);
      setProgress(null);
    }
  };

  const handleAlgorithmToggle = (algorithmKey: string) => {
    setSelectedAlgorithms(prev => 
      prev.includes(algorithmKey)
        ? prev.filter(key => key !== algorithmKey)
        : [...prev, algorithmKey]
    );
  };

  const getAlgorithmColor = (algorithmKey: string, index: number): string => {
    // Define a palette of distinct colors for better visualization
    const colors = [
      '#3B82F6', // Blue
      '#EF4444', // Red
      '#10B981', // Green
      '#F59E0B', // Yellow
      '#8B5CF6', // Purple
      '#EC4899', // Pink
      '#06B6D4', // Cyan
      '#84CC16', // Lime
      '#F97316', // Orange
      '#6366F1', // Indigo
      '#14B8A6', // Teal
      '#F43F5E', // Rose
      '#8B5A3C', // Brown
      '#6B7280', // Gray
      '#DC2626', // Dark Red
      '#059669', // Dark Green
      '#7C3AED', // Dark Purple
      '#DB2777', // Dark Pink
      '#0891B2', // Dark Cyan
      '#65A30D'  // Dark Lime
    ];
    
    // Use algorithm key to get consistent color assignment
    const colorIndex = selectedAlgorithms.indexOf(algorithmKey) % colors.length;
    return colors[colorIndex];
  };

  if (loading) {
    return (
      <div className="space-y-8">
        <div className="text-center">
          <h1 className="text-4xl font-bold text-gray-900 mb-2">
            Algorithm Usage Timeline
          </h1>
          <p className="text-xl text-gray-600">
            Track how the usage of AI algorithms in medical research has evolved over time
          </p>
        </div>

        <div className="bg-white p-8 rounded-lg shadow-lg max-w-2xl mx-auto">
          <div className="flex items-center justify-center mb-6">
            <Loader2 className="h-8 w-8 animate-spin text-blue-600" />
            <span className="ml-3 text-lg text-gray-700">Loading timeline data...</span>
          </div>
          
          {progress && (
            <div className="space-y-4">
              <div className="flex justify-between items-center">
                <span className="text-sm text-gray-600">
                  {progress.currentAlgorithm}
                </span>
                <span className="text-sm font-medium text-gray-900">
                  {Math.round((progress.current / progress.total) * 100)}%
                </span>
              </div>
              
              <div className="w-full bg-gray-200 rounded-full h-2">
                <div 
                  className="bg-blue-600 h-2 rounded-full transition-all duration-300 ease-out"
                  style={{ width: `${Math.min((progress.current / progress.total) * 100, 100)}%` }}
                ></div>
              </div>
              
              <div className="flex justify-between text-xs text-gray-500">
                <span>{progress.current} / {progress.total} requests</span>
                <span>
                  {progress.total > 0 ? Math.round((progress.current / progress.total) * 100) : 0}% complete
                </span>
              </div>
            </div>
          )}
          
          <div className="mt-6 p-4 bg-blue-50 rounded-lg">
            <div className="flex items-center mb-2">
              <Database className="h-4 w-4 text-blue-600 mr-2" />
              <span className="text-sm font-medium text-blue-900">Cache Information</span>
            </div>
            <p className="text-xs text-blue-700">
              Historical data is cached on disk to speed up future requests. 
              Only the current year data needs to be fetched from PubMed each time.
            </p>
          </div>
        </div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="text-center text-red-600 p-8">
        <p>{error}</p>
        <button 
          onClick={fetchTimelineData}
          className="mt-4 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
        >
          Retry
        </button>
      </div>
    );
  }

  const filteredTimelineData = timelineData.map(yearData => {
    const filtered: TimelineData = { year: yearData.year };
    selectedAlgorithms.forEach(algoKey => {
      if (yearData[algoKey] !== undefined) {
        filtered[algoKey] = yearData[algoKey];
      }
    });
    return filtered;
  });

  return (
    <div className="space-y-8">
      <div className="text-center">
        <h1 className="text-4xl font-bold text-gray-900 mb-2">
          Algorithm Usage Timeline
        </h1>
        <p className="text-xl text-gray-600">
          Track how the usage of AI algorithms in medical research has evolved over time
        </p>
      </div>

      <div className="bg-white p-6 rounded-lg shadow-lg">
        <div className="flex flex-col lg:flex-row lg:items-center lg:justify-between mb-6">
          <div className="flex items-center mb-4 lg:mb-0">
            <Calendar className="h-5 w-5 text-gray-500 mr-2" />
            <span className="text-sm font-medium text-gray-700">Year Range:</span>
            <input
              type="number"
              min="2010"
              max="2024"
              value={yearRange.start}
              onChange={(e) => setYearRange(prev => ({ ...prev, start: parseInt(e.target.value) }))}
              className="ml-2 px-2 py-1 border border-gray-300 rounded text-sm w-20"
            />
            <span className="mx-2 text-gray-500">to</span>
            <input
              type="number"
              min="2010"
              max="2024"
              value={yearRange.end}
              onChange={(e) => setYearRange(prev => ({ ...prev, end: parseInt(e.target.value) }))}
              className="px-2 py-1 border border-gray-300 rounded text-sm w-20"
            />
          </div>
          
          <div className="flex items-center space-x-6">
            <div className="flex items-center">
              <TrendingUp className="h-5 w-5 text-green-500 mr-2" />
              <span className="text-sm text-gray-600">
                {selectedAlgorithms.length} algorithm{selectedAlgorithms.length !== 1 ? 's' : ''} selected
              </span>
            </div>
            
            {cacheStats && (
              <div className="flex items-center space-x-4">
                <div className="flex items-center">
                  <Database className="h-4 w-4 text-blue-500 mr-1" />
                  <span className="text-xs text-gray-600">
                    {cacheStats.cached} cached
                  </span>
                </div>
                <div className="flex items-center">
                  <Clock className="h-4 w-4 text-orange-500 mr-1" />
                  <span className="text-xs text-gray-600">
                    {cacheStats.fetched} fetched
                  </span>
                </div>
              </div>
            )}
          </div>
        </div>

        <ResponsiveContainer width="100%" height={500}>
          <LineChart data={filteredTimelineData}>
            <CartesianGrid strokeDasharray="3 3" />
            <XAxis 
              dataKey="year" 
              type="number"
              scale="linear"
              domain={[yearRange.start, yearRange.end]}
            />
            <YAxis />
            <Tooltip />
            <Legend />
            {selectedAlgorithms.map((algoKey, index) => {
              const algo = algorithms.find(a => a.algorithm === algoKey);
              if (!algo) return null;
              
              return (
                <Line
                  key={algoKey}
                  type="monotone"
                  dataKey={algoKey}
                  stroke={getAlgorithmColor(algoKey, index)}
                  strokeWidth={2}
                  name={algo.name}
                  connectNulls={false}
                />
              );
            })}
          </LineChart>
        </ResponsiveContainer>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
        <div className="bg-white p-6 rounded-lg shadow-lg">
          <h3 className="text-lg font-bold text-gray-900 mb-4">Classical ML</h3>
          <div className="space-y-2">
            {algorithms
              .filter(algo => algo.category === 'classical_ml')
              .slice(0, 8)
              .map(algo => (
                <label key={algo.algorithm} className="flex items-center cursor-pointer">
                  <input
                    type="checkbox"
                    checked={selectedAlgorithms.includes(algo.algorithm)}
                    onChange={() => handleAlgorithmToggle(algo.algorithm)}
                    className="mr-2"
                  />
                  <span className="text-sm text-gray-700">{algo.name}</span>
                </label>
              ))}
          </div>
        </div>

        <div className="bg-white p-6 rounded-lg shadow-lg">
          <h3 className="text-lg font-bold text-gray-900 mb-4">Deep Learning</h3>
          <div className="space-y-2">
            {algorithms
              .filter(algo => algo.category === 'deep_learning')
              .slice(0, 8)
              .map(algo => (
                <label key={algo.algorithm} className="flex items-center cursor-pointer">
                  <input
                    type="checkbox"
                    checked={selectedAlgorithms.includes(algo.algorithm)}
                    onChange={() => handleAlgorithmToggle(algo.algorithm)}
                    className="mr-2"
                  />
                  <span className="text-sm text-gray-700">{algo.name}</span>
                </label>
              ))}
          </div>
        </div>

        <div className="bg-white p-6 rounded-lg shadow-lg">
          <h3 className="text-lg font-bold text-gray-900 mb-4">Large Language Models</h3>
          <div className="space-y-2">
            {algorithms
              .filter(algo => algo.category === 'llms')
              .slice(0, 8)
              .map(algo => (
                <label key={algo.algorithm} className="flex items-center cursor-pointer">
                  <input
                    type="checkbox"
                    checked={selectedAlgorithms.includes(algo.algorithm)}
                    onChange={() => handleAlgorithmToggle(algo.algorithm)}
                    className="mr-2"
                  />
                  <span className="text-sm text-gray-700">{algo.name}</span>
                </label>
              ))}
          </div>
        </div>
      </div>
    </div>
  );
};

export default Timeline;