import React, { useState, useEffect } from 'react';
import {
  LineChart,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer
} from 'recharts';
import { PROVIDERS_MAP } from '../../utils/providers';
import {
  fetchAllModelData,
  generateMonthlyData,
  getTotalMonthlyData,
  processDetailedModelData,
  MonthlyActivity,
  DetailedModelData,
  convertToCSV
} from '../../utils/modelData';
import Link from 'next/link';

interface TrendProps {
  monthlyData: MonthlyActivity[];
  totalData: MonthlyActivity[];
  detailedData: DetailedModelData[];
  error?: string;
}

const COLORS = Object.fromEntries(
  Object.entries(PROVIDERS_MAP).map(([provider, { color }]) => [provider, color])
);
COLORS['Total'] = '#4CAF50';

const CustomTooltip = ({ active, payload, label }: any) => {
  if (active && payload && payload.length) {
    return (
      <div className="bg-white p-4 border border-gray-200 rounded shadow dark:bg-gray-800 dark:border-gray-700">
        <p className="text-sm font-bold mb-2 dark:text-white">{label}</p>
        {payload.map((entry: any) => (
          <p
            key={entry.name}
            className="text-sm"
            style={{ color: entry.color }}
          >
            {entry.name}: {entry.value} models
          </p>
        ))}
      </div>
    );
  }
  return null;
};

const formatDate = (dateStr: string) => {
  const date = new Date(dateStr);
  return date.toLocaleDateString('en-US', { 
    year: 'numeric',
    month: 'short',
    day: 'numeric'
  });
};

const TrendPage: React.FC<TrendProps> = ({ monthlyData = [], totalData = [], detailedData = [], error }) => {
  const [showTotal, setShowTotal] = useState(true);
  const [selectedProviders, setSelectedProviders] = useState<string[]>([]);
  const [minLikes, setMinLikes] = useState(100);
  const [isLoading, setIsLoading] = useState(false);
  const [contentType, setContentType] = useState<'all' | 'models' | 'datasets'>('all');

  const toggleProvider = (provider: string) => {
    setSelectedProviders(prev => 
      prev.includes(provider)
        ? prev.filter(p => p !== provider)
        : [...prev, provider]
    );
  };

  // Filter total data based on content type
  const filteredTotalData = totalData.filter(d => {
    if (contentType === 'all') {
      return d.isDataset === null;  // Show only combined counts for 'all'
    }
    return (contentType === 'datasets' && d.isDataset === true) ||
           (contentType === 'models' && d.isDataset === false);
  });

  // Group data by provider
  const providerData = Object.fromEntries(
    Object.keys(PROVIDERS_MAP).map(provider => {
      const providerMonthlyData = monthlyData.filter(d => {
        if (contentType === 'all') {
          return d.provider === provider;  // Show all items for the provider
        }
        const matchesContentType = (contentType === 'datasets' && d.isDataset === true) ||
                                 (contentType === 'models' && d.isDataset === false);
        return d.provider === provider && matchesContentType;
      });

      // If showing all, aggregate the counts for each month
      if (contentType === 'all') {
        const aggregatedData: Record<string, MonthlyActivity> = {};
        providerMonthlyData.forEach(d => {
          if (!aggregatedData[d.date]) {
            aggregatedData[d.date] = {
              date: d.date,
              count: 0,
              provider: d.provider,
              isDataset: null
            };
          }
          aggregatedData[d.date].count += d.count;
        });
        return [provider, Object.values(aggregatedData).sort((a, b) => a.date.localeCompare(b.date))];
      }

      return [provider, providerMonthlyData || []];
    })
  );

  // Filter and group detailed model data
  const filteredModels = (detailedData || [])
    .filter(model => {
      const matchesContentType = contentType === 'all' || 
                               (contentType === 'datasets' && model.isDataset) ||
                               (contentType === 'models' && !model.isDataset);
      
      return model.likes >= minLikes && 
        (selectedProviders.length === 0 || selectedProviders.includes(model.provider)) &&
        matchesContentType;
    })
    .reduce<Record<string, DetailedModelData[]>>((acc, model) => {
      if (!acc[model.monthKey]) {
        acc[model.monthKey] = [];
      }
      acc[model.monthKey].push(model);
      return acc;
    }, {});

  useEffect(() => {
    console.log('Content type changed:', contentType);
    console.log('Selected providers:', selectedProviders);
    console.log('Min likes:', minLikes);
  }, [contentType, selectedProviders, minLikes]);

  if (error) {
    return (
      <div className="w-full max-w-screen-xl mx-auto p-4">
        <h1 className="text-3xl lg:text-5xl mt-16 font-bold text-center mb-2 dark:text-white">Chinese AI Model Release Trends 📈</h1>
        <div className="text-center text-red-600 dark:text-red-400 mt-8">
          <p>Error loading data: {error}</p>
          <p className="mt-2">Please try again later.</p>
        </div>
      </div>
    );
  }

  return (
    <div className="w-full max-w-screen-lg mx-auto p-4">
      <div className="flex justify-between items-center mb-8">
        <div>
          <h1 className="text-3xl lg:text-4xl font-bold mb-2">Chinese AI Open Source Trends 🤗</h1>
          <p className="text-gray-600 dark:text-gray-400">
            Track the growth of Chinese AI models and datasets over time
          </p>
        </div>
        <Link 
          href="/heatmap"
          className="px-4 py-2 rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors"
        >
          View Heatmap
        </Link>
      </div>
      <p className="text-center text-sm mb-8 dark:text-gray-300">
        Track the growth of Chinese AI models and datasets over time
      </p>
      
      <div className="flex flex-col gap-4 p-4">
        <div className="flex justify-center mb-6 space-x-4">
          <button
            onClick={() => setContentType('all')}
            className={`px-4 py-2 rounded-lg ${
              contentType === 'all'
                ? 'bg-blue-500 text-white'
                : 'bg-gray-200 text-gray-700 dark:bg-gray-700 dark:text-gray-300'
            }`}
          >
            All
          </button>
          <button
            onClick={() => setContentType('models')}
            className={`px-4 py-2 rounded-lg ${
              contentType === 'models'
                ? 'bg-blue-500 text-white'
                : 'bg-gray-200 text-gray-700 dark:bg-gray-700 dark:text-gray-300'
            }`}
          >
            Models
          </button>
          <button
            onClick={() => setContentType('datasets')}
            className={`px-4 py-2 rounded-lg ${
              contentType === 'datasets'
                ? 'bg-blue-500 text-white'
                : 'bg-gray-200 text-gray-700 dark:bg-gray-700 dark:text-gray-300'
            }`}
          >
            Datasets
          </button>
        </div>

        <div className="flex flex-wrap gap-4 mb-6 justify-center items-center">
          <div className="flex gap-2">
            <button
              onClick={() => setShowTotal(!showTotal)}
              className={`px-4 py-2 rounded-lg ${
                showTotal
                  ? 'bg-blue-500 text-white'
                  : 'bg-gray-200 text-gray-700 dark:bg-gray-700 dark:text-gray-300'
              }`}
            >
              {showTotal ? 'Hide Total' : 'Show Total'}
            </button>
            {Object.entries(PROVIDERS_MAP).map(([provider, { color }]) => (
              <button
                key={provider}
                onClick={() => toggleProvider(provider)}
                className={`px-4 py-2 rounded-lg transition-colors ${
                  selectedProviders.includes(provider)
                    ? 'text-white'
                    : 'text-gray-600 dark:text-gray-400'
                }`}
                style={{
                  backgroundColor: selectedProviders.includes(provider)
                    ? color
                    : 'transparent'
                }}
              >
                {provider}
              </button>
            ))}
          </div>
        </div>

        {/* Chart */}
        <div className="w-full h-[600px] dark:bg-gray-900 p-4 rounded-lg">
          <ResponsiveContainer width="100%" height="100%">
            <LineChart
              margin={{ top: 20, right: 30, left: 20, bottom: 20 }}
            >
              <CartesianGrid strokeDasharray="3 3" stroke="#374151" />
              <XAxis
                dataKey="date"
                type="category"
                allowDuplicatedCategory={false}
                tick={{ fontSize: 12 }}
                interval="preserveStartEnd"
                stroke="#9CA3AF"
              />
              <YAxis stroke="#9CA3AF" />
              <Tooltip content={<CustomTooltip />} />
              <Legend />
              
              {/* Total Line */}
              {showTotal && (
                <Line
                  data={filteredTotalData}
                  type="monotone"
                  dataKey="count"
                  stroke={COLORS['Total']}
                  name="Total"
                  strokeWidth={2}
                  dot={false}
                />
              )}

              {/* Provider Lines */}
              {selectedProviders.map(provider => (
                <Line
                  key={provider}
                  data={providerData[provider]}
                  type="monotone"
                  dataKey="count"
                  stroke={COLORS[provider]}
                  name={provider}
                  strokeWidth={1.5}
                  dot={false}
                />
              ))}
            </LineChart>
          </ResponsiveContainer>
        </div>

        {/* Download Button */}
        <div className="flex justify-center mt-4 mb-8">
          <button
            className="px-4 py-2 rounded-lg bg-green-500 text-white hover:bg-green-600"
            onClick={() => {
              // Get the currently visible data based on filters
              const visibleData = [];
              
              // Add provider data if showing
              selectedProviders.forEach(provider => {
                visibleData.push(...providerData[provider].map(d => ({ ...d, provider })));
              });
              
              // Add total data if showing
              if (showTotal) {
                visibleData.push(...filteredTotalData);
              }

              const csvContent = convertToCSV(visibleData);
              const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
              const link = document.createElement('a');
              link.href = URL.createObjectURL(blob);
              link.download = `${contentType}_counts.csv`;
              link.click();
              URL.revokeObjectURL(link.href);
            }}
          >
            Download CSV
          </button>
        </div>

        {/* Major Releases Section */}
        <div className="mt-12">
          <div className="flex items-center justify-between mb-6">
            <h2 className="text-2xl font-bold dark:text-white">
              Major Releases ({Object.values(filteredModels).flat().length})
            </h2>
            <div className="flex items-center gap-3 bg-white dark:bg-gray-800 px-4 py-2 rounded-lg shadow-sm">
              <label className="text-sm font-medium dark:text-gray-300">Min Likes:</label>
              <input
                type="number"
                value={minLikes}
                onChange={(e) => setMinLikes(Math.max(0, parseInt(e.target.value) || 0))}
                className="w-20 px-2 py-1 border rounded dark:bg-gray-700 dark:border-gray-600 dark:text-white focus:outline-none focus:ring-2 focus:ring-green-500"
              />
            </div>
          </div>
          <div className="space-y-8">
            {Object.entries(filteredModels)
              .map(([monthKey, models]) => ({
                monthKey,
                models,
                sortKey: models[0]?.sortKey || '' // Use the first model's sortKey
              }))
              .sort((a, b) => b.sortKey.localeCompare(a.sortKey)) // Sort by sortKey in descending order
              .map(({ monthKey, models }) => (
                <div key={monthKey} className="border-b border-gray-200 dark:border-gray-700 pb-4">
                  <h3 className="text-xl font-semibold mb-3 dark:text-white">{monthKey}</h3>
                  <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
                    {models
                      .sort((a, b) => b.likes - a.likes) // Sort models within each month by likes
                      .map(model => (
                      <div
                        key={model.id}
                        className="p-4 rounded-lg border dark:border-gray-700 hover:shadow-md transition-shadow bg-white dark:bg-gray-800"
                        style={{ borderColor: COLORS[model.provider] }}
                      >
                        <div className="flex justify-between items-start">
                          <div>
                            <a
                              href={`https://huggingface.co/${model.id}`}
                              target="_blank"
                              rel="noopener noreferrer"
                              className="text-blue-600 hover:underline font-medium dark:text-blue-400"
                            >
                              {model.name}
                            </a>
                            <p className="text-sm text-gray-600 dark:text-gray-400">{model.provider}</p>
                          </div>
                          <div className="text-right">
                            <p className="text-sm font-medium dark:text-white">❤️ {model.likes}</p>
                            <p className="text-xs text-gray-500 dark:text-gray-400">{formatDate(model.createdAt)}</p>
                          </div>
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
              ))}
          </div>
        </div>
      </div>
    </div>
  );
};

export const getStaticProps = async () => {
  try {
    const modelData = await fetchAllModelData();
    const monthlyData = generateMonthlyData(modelData);
    const totalData = getTotalMonthlyData(monthlyData);
    const filteredModels = processDetailedModelData(modelData);

    return {
      props: {
        monthlyData,
        totalData,
        filteredModels,
      },
      // Revalidate every 12 hours
      revalidate: 43200,
    };
  } catch (error) {
    console.error('Error in getStaticProps:', error);
    return {
      props: {
        monthlyData: [],
        totalData: [],
        filteredModels: {},
      },
      // Retry more frequently if there was an error
      revalidate: 3600,
    };
  }
};

export default TrendPage;
