import useSWR from "swr";
import { FrigateStats } from "@/types/stats";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useFrigateStats } from "@/api/ws";
import { EmbeddingThreshold, GenAIThreshold, Threshold } from "@/types/graph";
import { Skeleton } from "@/components/ui/skeleton";
import { ThresholdBarGraph } from "@/components/graph/SystemGraph";
import { cn } from "@/lib/utils";
import { useTranslation } from "react-i18next";
import { EventsPerSecondsLineGraph } from "@/components/graph/LineGraph";

type EnrichmentMetricsProps = {
  lastUpdated: number;
  setLastUpdated: (last: number) => void;
};
export default function EnrichmentMetrics({
  lastUpdated,
  setLastUpdated,
}: EnrichmentMetricsProps) {
  // stats
  const { t } = useTranslation(["views/system"]);

  const { data: initialStats } = useSWR<FrigateStats[]>(
    ["stats/history", { keys: "embeddings,service" }],
    {
      revalidateOnFocus: false,
    },
  );

  const [statsHistory, setStatsHistory] = useState<FrigateStats[]>([]);
  const updatedStats = useFrigateStats();

  useEffect(() => {
    if (initialStats == undefined || initialStats.length == 0) {
      return;
    }

    if (statsHistory.length == 0) {
      setStatsHistory(initialStats);
      return;
    }

    if (!updatedStats) {
      return;
    }

    if (updatedStats.service.last_updated > lastUpdated) {
      setStatsHistory([...statsHistory.slice(1), updatedStats]);
      setLastUpdated(Date.now() / 1000);
    }
  }, [initialStats, updatedStats, statsHistory, lastUpdated, setLastUpdated]);

  const getThreshold = useCallback((key: string) => {
    if (key.includes("description")) {
      return GenAIThreshold;
    }

    return EmbeddingThreshold;
  }, []);

  // timestamps

  const updateTimes = useMemo(
    () => statsHistory.map((stats) => stats.service.last_updated),
    [statsHistory],
  );

  // features stats

  const embeddingInferenceTimeSeries = useMemo(() => {
    if (!statsHistory) {
      return [];
    }

    const series: {
      [key: string]: {
        name: string;
        metrics: Threshold;
        data: { x: number; y: number }[];
      };
    } = {};

    statsHistory.forEach((stats, statsIdx) => {
      if (!stats?.embeddings) {
        return;
      }

      Object.entries(stats.embeddings).forEach(([rawKey, stat]) => {
        const key = rawKey.replaceAll("_", " ");

        if (!(key in series)) {
          series[key] = {
            name: t("enrichments.embeddings." + rawKey),
            metrics: getThreshold(rawKey),
            data: [],
          };
        }

        series[key].data.push({ x: statsIdx + 1, y: stat });
      });
    });
    return Object.values(series);
  }, [statsHistory, t, getThreshold]);

  return (
    <>
      <div className="scrollbar-container mt-4 flex size-full flex-col overflow-y-auto">
        <div className="text-sm font-medium text-muted-foreground">
          {t("enrichments.title")}
        </div>
        <div
          className={cn(
            "mt-4 grid w-full grid-cols-1 gap-2 sm:grid-cols-3",
            embeddingInferenceTimeSeries && "sm:grid-cols-4",
          )}
        >
          {statsHistory.length != 0 ? (
            <>
              {embeddingInferenceTimeSeries.map((series) => (
                <div className="rounded-lg bg-background_alt p-2.5 md:rounded-2xl">
                  <div className="mb-5 smart-capitalize">{series.name}</div>
                  {series.name.endsWith("Speed") ? (
                    <ThresholdBarGraph
                      key={series.name}
                      graphId={`${series.name}-inference`}
                      name={series.name}
                      unit="ms"
                      threshold={series.metrics}
                      updateTimes={updateTimes}
                      data={[series]}
                    />
                  ) : (
                    <EventsPerSecondsLineGraph
                      key={series.name}
                      graphId={`${series.name}-fps`}
                      unit=""
                      name={t("enrichments.infPerSecond")}
                      updateTimes={updateTimes}
                      data={[series]}
                    />
                  )}
                </div>
              ))}
            </>
          ) : (
            <Skeleton className="aspect-video w-full rounded-lg md:rounded-2xl" />
          )}
        </div>
      </div>
    </>
  );
}
