import React, { useState, useEffect } from 'react';
import ActivityCalendar from "react-activity-calendar";
import { Tooltip } from '@mui/material';

const PROVIDERS_MAP = {
  "akhaliq": { color: "#ff5733", authors: ["akhaliq"] },
  "Sylvain Filoni": { color: "#33ff57", authors: ["fffiloni"] },
  "multimodalart": { color: "#3357ff", authors: ["multimodalart"] },
  "PeepDaSlan9": { color: "#ff33a1", authors: ["PeepDaSlan9"] },
  "Omnibus": { color: "#a1ff33", authors: ["Omnibus"] },
  "ysharma": { color: "#ffa133", authors: ["ysharma"] },
  "merve": { color: "#33a1ff", authors: ["merve"] },
  "Tonic": { color: "#a133ff", authors: ["Tonic"] },
  "radames": { color: "#ff3366", authors: ["radames"] },
  "Xenova": { color: "#33ffcc", authors: ["Xenova"] },
  "jbilcke": { color: "#cc33ff", authors: ["jbilcke-hf"] },
  "tonyassi": { color: "#ffcc33", authors: ["tonyassi"] },
  "ehristoforu": { color: "#33ccff", authors: ["ehristoforu"] },
  "artificialguybr": { color: "#ccff33", authors: ["artificialguybr"] },
  "prithivMLmods": { color: "#ff6633", authors: ["prithivMLmods"] },
  "Nymbo": { color: "#55fac0", authors: ["Nymbo"] },
};

interface ModelData {
  createdAt: string;
  id: string;
}

interface Activity {
  date: string;
  count: number;
  level: number;
}

export default function OpenSourceHeatmap() {
  const [calendarData, setCalendarData] = useState<Record<string, Activity[]>>({});
  const [isLoading, setIsLoading] = useState(true);

  const generateCalendarData = (modelData: ModelData[]) => {
    const data: Record<string, Activity[]> = Object.fromEntries(
      Object.keys(PROVIDERS_MAP).map(provider => [provider, []])
    );

    const today = new Date();
    const startDate = new Date(today);
    startDate.setMonth(today.getMonth() - 11);
    startDate.setDate(1);

    // create a map to store counts for each provider and date
    const countMap: Record<string, Record<string, number>> = {};

    modelData.forEach(item => {
      const dateString = item.createdAt.split('T')[0];
      Object.entries(PROVIDERS_MAP).forEach(([provider, { authors }]) => {
        if (authors.some(author => item.id.startsWith(author))) {
          countMap[provider] = countMap[provider] || {};
          countMap[provider][dateString] = (countMap[provider][dateString] || 0) + 1;
        }
      });
    });

    // fill in with 0s for days with no activity
    for (let d = new Date(startDate); d <= today; d.setDate(d.getDate() + 1)) {
      const dateString = d.toISOString().split('T')[0];
      
      Object.entries(PROVIDERS_MAP).forEach(([provider]) => {
        const count = countMap[provider]?.[dateString] || 0;
        data[provider].push({ date: dateString, count, level: 0 });
      });
    }

    // calculate average counts for each provider
    const avgCounts = Object.fromEntries(
      Object.entries(data).map(([provider, days]) => [
        provider,
        days.reduce((sum, day) => sum + day.count, 0) / days.length || 0
      ])
    );

    // assign levels based on count relative to average
    Object.entries(data).forEach(([provider, days]) => {
      const avgCount = avgCounts[provider];
      days.forEach(day => {
        day.level = 
          day.count === 0 ? 0 :
          day.count <= avgCount * 0.5 ? 1 :
          day.count <= avgCount ? 2 :
          day.count <= avgCount * 1.5 ? 3 : 4;
      });
    });

    return data;
  }

  const initData = async () => {
    try {
      const allAuthors = Object.values(PROVIDERS_MAP).flatMap(({ authors }) => authors);
      const uniqueAuthors = Array.from(new Set(allAuthors));

      const allModelData = await Promise.all(
        uniqueAuthors.map(async (author) => {
          const response = await fetch(`https://huggingface.co/api/spaces?author=${author}&sort=createdAt&direction=-1`);
          const data = await response.json();
          return data.map((item: any) => ({
            createdAt: item.createdAt,
            id: item.id,
          }));
        })
      );

      const flatModelData = allModelData.flat();
      const calendarData = generateCalendarData(flatModelData);
      setCalendarData(calendarData);
    } catch (error) {
      console.error("Error fetching data:", error);
    } finally {
      setIsLoading(false);
    }
  }

  useEffect(() => {
    initData();
  }, []);

  return (
    <div className="w-full max-w-screen-lg mx-auto p-4">
      <h1 className="text-3xl lg:text-5xl mt-16 font-bold text-center mb-2">Hugging Face Heatmap 🤗</h1>
      <p className="text-center text-sm mb-8">Heatmaps of new spaces created by some of the most active creators.</p>
      {isLoading ? (
        <p className="text-center">Loading...</p>
      ) : (
        <div className="space-y-8 mx-10">
          {Object.entries(PROVIDERS_MAP)
            .sort(([keyA], [keyB]) => 
              calendarData[keyB].reduce((sum, day) => sum + day.count, 0) -
              calendarData[keyA].reduce((sum, day) => sum + day.count, 0)
            )
            .map(([providerName, { color }]) => (
              <div key={providerName} className="flex flex-col">
                <h2 className="text-xl font-bold mb-2">{providerName}</h2>
                <div className="w-full overflow-x-auto">
                  <div className="inline-block mx-auto">
                    <ActivityCalendar 
                      data={calendarData[providerName]}
                      theme={{
                        dark: ['#161b22', color],
                        light: ['#e0e0e0', color],
                      }}
                      hideTotalCount
                      renderBlock={(block, activity) => (
                        <Tooltip
                          title={`${activity.count} Spaces created on ${activity.date}`}
                          arrow
                        >
                          {block}
                        </Tooltip>
                      )}
                    />
                  </div>
                </div>
              </div>
            ))
          }
        </div>
      )}
    </div>
  );
}