"use client";
// /components/main/system/DetailModal.tsx
import React, { useEffect, useRef, useState, useCallback } from "react";
import { Line } from "react-chartjs-2";
import { useSelector } from "react-redux";
import { RootState, useAppDispatch } from "@/redux/store";
import { setFullScreen } from "@/redux/slices/kabelueberwachungChartSlice";
import { resetDateRange } from "@/redux/slices/dateRangePickerSlice";

// Import Thunks
import SystemChartActionBar from "@/components/main/system/SystemChartActionBar";
import { getSystemspannung5VplusThunk } from "@/redux/thunks/getSystemspannung5VplusThunk";
import { getSystemspannung15VplusThunk } from "@/redux/thunks/getSystemspannung15VplusThunk";
import { getSystemspannung15VminusThunk } from "@/redux/thunks/getSystemspannung15VminusThunk";
import { getSystemspannung98VminusThunk } from "@/redux/thunks/getSystemspannung98VminusThunk";
import { getTemperaturAdWandlerThunk } from "@/redux/thunks/getTemperaturAdWandlerThunk";
import { getTemperaturProzessorThunk } from "@/redux/thunks/getTemperaturProzessorThunk";

import {
  Chart as ChartJS,
  LineElement,
  PointElement,
  CategoryScale,
  LinearScale,
  Title,
  Tooltip,
  Legend,
  Filler,
  TimeScale,
  type ChartDataset,
  type ChartOptions,
  type ChartData,
  type Chart,
} from "chart.js";

import "chartjs-adapter-date-fns";
import { de } from "date-fns/locale";

ChartJS.register(
  LineElement,
  PointElement,
  CategoryScale,
  LinearScale,
  Title,
  Tooltip,
  Legend,
  Filler,
  TimeScale
);

// Tailwind-basierte Farbdefinitionen für Chart.js
const chartColors = {
  gray: {
    line: "#6B7280", // tailwind gray-500
    background: "rgba(107, 114, 128, 0.2)", // tailwind gray-500 mit opacity
  },
  littwinBlue: {
    line: "#00AEEF", // littwin-blue
    background: "rgba(0, 174, 239, 0.2)", // littwin-blue mit opacity
  },
};

type ReduxDataEntry = {
  //Alle DIA0 t,m,i,a , DIA1 und DIA2 t,i,a,g
  t: string; // Zeitstempel
  i: number; // Minimum
  a: number; // Maximum
  g?: number; // Durchschnitt (optional, falls vorhanden)
  m?: number; // aktueller Messwert (optional, falls vorhanden)
};

const chartOptions: ChartOptions<"line"> = {
  responsive: true,
  maintainAspectRatio: false,
  plugins: {
    legend: { position: "top" as const },
    title: {
      display: true,
      text: "Verlauf",
    },
    tooltip: {
      mode: "index" as const,
      intersect: false,
      callbacks: {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        label: function (ctx: any) {
          return `Messwert: ${ctx.parsed.y}`;
        },
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        title: function (items: any[]) {
          const date = items[0].parsed.x;
          return `Zeitpunkt: ${new Date(date).toLocaleString("de-DE")}`;
        },
      },
    },
    zoom: {
      pan: { enabled: true, mode: "x" as const },
      zoom: {
        wheel: { enabled: true },
        pinch: { enabled: true },
        mode: "x" as const,
      },
    },
  },
  scales: {
    x: {
      type: "time" as const,
      time: {
        unit: "day" as const,
        tooltipFormat: "dd.MM.yyyy HH:mm",
        displayFormats: {
          day: "dd.MM.yyyy",
        },
      },
      adapters: {
        date: { locale: de },
      },
      title: {
        display: true,
        text: "Zeit",
      },
    },
    y: {
      title: {
        display: true,
        text: "Messwert",
      },
    },
  },
};

type Props = {
  isOpen: boolean;
  selectedKey: string | null;
  onClose: () => void;
  zeitraum: "DIA0" | "DIA1" | "DIA2";
  setZeitraum: (typ: "DIA0" | "DIA1" | "DIA2") => void;
};

export const DetailModal = ({
  isOpen,
  selectedKey,
  onClose,
  zeitraum,
  setZeitraum,
}: Props) => {
  // Stable empty reference to avoid React-Redux dev warning about selector returning new [] each call
  const EMPTY_REDUX_DATA: ReadonlyArray<ReduxDataEntry> = Object.freeze([]);
  const chartRef = useRef<Chart<"line"> | null>(null);
  const [chartData, setChartData] = useState<ChartData<"line">>({
    datasets: [],
  });
  const [isLoading, setIsLoading] = useState(false);
  const [shouldUpdateChart, setShouldUpdateChart] = useState(false);
  // const [forceUpdate, setForceUpdate] = useState(0); // Für periodische UI-Updates (derzeit nicht benötigt)

  const reduxData = useSelector((state: RootState) => {
    switch (selectedKey) {
      case "+5V":
        return state.systemspannung5Vplus[zeitraum];
      case "+15V":
        return state.systemspannung15Vplus[zeitraum];
      case "-15V":
        return state.systemspannung15Vminus[zeitraum];
      case "-98V":
        return state.systemspannung98Vminus[zeitraum];
      case "ADC Temp":
        return state.temperaturAdWandler[zeitraum];
      case "CPU Temp":
        return state.temperaturProzessor[zeitraum];
      default:
        return EMPTY_REDUX_DATA;
    }
  }) as ReduxDataEntry[];

  const isFullScreen = useSelector(
    (state: RootState) => state.kabelueberwachungChartSlice.isFullScreen
  );
  const dispatch = useAppDispatch();

  // API-Request beim Klick auf "Daten laden" - memoized für useEffect dependency
  const handleFetchData = useCallback(() => {
    setIsLoading(true);

    // Clear previous chart data
    setChartData({ datasets: [] });

    // Flag setzen, dass Chart nach Datenempfang aktualisiert werden soll
    setShouldUpdateChart(true);

    switch (selectedKey) {
      case "+5V":
        dispatch(getSystemspannung5VplusThunk(zeitraum));
        break;
      case "+15V":
        dispatch(getSystemspannung15VplusThunk(zeitraum));
        break;
      case "-15V":
        dispatch(getSystemspannung15VminusThunk(zeitraum));
        break;
      case "-98V":
        dispatch(getSystemspannung98VminusThunk(zeitraum));
        break;
      case "ADC Temp":
        dispatch(getTemperaturAdWandlerThunk(zeitraum));
        break;
      case "CPU Temp":
        dispatch(getTemperaturProzessorThunk(zeitraum));
        break;
      default:
        break;
    }
  }, [selectedKey, zeitraum, dispatch]);

  // Reset Zeitraum auf DIA0 und Datumswerte wenn Modal geöffnet wird
  useEffect(() => {
    if (isOpen) {
      setZeitraum("DIA0");
      // Reset DateRangePicker to its defaults (it sets 30 days → today on mount)
      dispatch(resetDateRange());

      // Chart-Daten zurücksetzen beim Öffnen
      setChartData({ datasets: [] });
    }
  }, [isOpen, setZeitraum, dispatch]);

  // Periodische UI-Updates alle 2 Sekunden während Wartezeit
  useEffect(() => {
    if (isOpen && (!chartData.datasets || chartData.datasets.length === 0)) {
      // Optional: periodische Re-Renders wurden deaktiviert, da nicht mehr notwendig
      // (kann wieder aktiviert werden falls Cursor-Animation erwünscht ist)
    }
  }, [isOpen, chartData.datasets]);

  // Automatisches "Daten laden" alle 4 Sekunden, maximal 2 Versuche
  useEffect(() => {
    if (isOpen && (!chartData.datasets || chartData.datasets.length === 0)) {
      let attempts = 0;
      const interval = setInterval(() => {
        if (attempts < 2) {
          console.log("Auto-clicking 'Daten laden' button...");
          handleFetchData();
          attempts++;
        } else {
          clearInterval(interval);
        }
      }, 4000);

      return () => clearInterval(interval);
    }
  }, [isOpen, chartData.datasets, handleFetchData]);

  const toggleFullScreen = () => {
    dispatch(setFullScreen(!isFullScreen));
    setTimeout(() => {
      chartRef.current?.resize();
    }, 50);
  };

  const handleClose = () => {
    dispatch(setFullScreen(false));
    dispatch(resetDateRange());
    onClose();
  };

  useEffect(() => {
    const loadZoomPlugin = async () => {
      if (typeof window !== "undefined") {
        const zoomPlugin = (await import("chartjs-plugin-zoom")).default;
        if (!ChartJS.registry.plugins.get("zoom")) {
          ChartJS.register(zoomPlugin);
        }
      }
    };
    loadZoomPlugin();
  }, []);

  useEffect(() => {
    if (chartRef.current && selectedKey) {
      const opts = chartRef.current.options as ChartOptions<"line"> & {
        plugins?: { title?: { text?: string } };
      };
      if (opts.plugins?.title) {
        opts.plugins.title.text = `Verlauf ${selectedKey}`;
      }
      chartRef.current.update("none");
    }
  }, [selectedKey]);

  useEffect(() => {
    if (chartRef.current) {
      chartRef.current.resetZoom();
    }
  }, [zeitraum]);

  // Chart.js animation complete callback to set isLoading false
  useEffect(() => {
    if (chartRef.current && isLoading) {
      const chartInstance = chartRef.current;
      // Save previous callback to restore later
      const animation: any = chartInstance.options.animation || {}; // eslint-disable-line @typescript-eslint/no-explicit-any
      const prevCallback = animation.onComplete;
      animation.onComplete = () => {
        setIsLoading(false);
        if (typeof prevCallback === "function") prevCallback();
      };
      chartInstance.options.animation = animation;
      chartInstance.update();
    }
  }, [chartData, isLoading]);

  // DateRange from global DateRangePicker slice
  const pickerVonDatum = useSelector(
    (state: RootState) => state.dateRangePicker.vonDatum
  );
  const pickerBisDatum = useSelector(
    (state: RootState) => state.dateRangePicker.bisDatum
  );

  // Update chart data when Redux data changes (only after button click)
  useEffect(() => {
    if (shouldUpdateChart && reduxData && reduxData.length > 0) {
      // Filter data by selected date range (inclusive end date)
      let filtered = reduxData;
      try {
        if (pickerVonDatum && pickerBisDatum) {
          const start = new Date(`${pickerVonDatum}T00:00:00`);
          const end = new Date(`${pickerBisDatum}T23:59:59`);
          const s = start.getTime();
          const e = end.getTime();
          filtered = reduxData.filter((entry) => {
            const t = new Date(entry.t).getTime();
            return t >= s && t <= e;
          });
        }
      } catch (err) {
        console.warn("Zeitfilter konnte nicht angewendet werden:", err);
      }

      console.log("Redux data for chart (filtered):", filtered.length);
      if (!filtered.length) {
        setChartData({ datasets: [] });
        setShouldUpdateChart(false);
        return;
      }

      // Create datasets array for multiple lines
      const datasets: ChartDataset<"line">[] = [];

      // Check which data fields are available and create datasets accordingly
      const hasMinimum = filtered.some(
        (entry) => entry.i !== undefined && entry.i !== null && entry.i !== 0
      );
      const hasMaximum = filtered.some(
        (entry) => entry.a !== undefined && entry.a !== null
      );
      const hasAverage = filtered.some(
        (entry) => entry.g !== undefined && entry.g !== null
      );
      const hasCurrent = filtered.some(
        (entry) => entry.m !== undefined && entry.m !== null
      );

      // Zuerst Hintergrund-Linien (Minimum/Maximum) - grau
      if (hasMinimum) {
        datasets.push({
          label: "Messwert Minimum",
          data: filtered.map((entry) => ({
            x: new Date(entry.t).getTime(),
            y: entry.i || 0,
          })),
          borderColor: "gray",
          borderWidth: 1,
          pointRadius: 0,
          tension: 0.1,
          order: 1,
        });
      }

      if (hasMaximum) {
        datasets.push({
          label: "Messwert Maximum",
          data: filtered.map((entry) => ({
            x: new Date(entry.t).getTime(),
            y: entry.a || 0,
          })),
          borderColor: "gray",
          borderWidth: 1,
          pointRadius: 0,
          tension: 0.1,
          order: 3,
        });
      }

      // Dann Vordergrund-Linien (Durchschnitt/Messwert) - littwin-blue
      if (hasAverage) {
        datasets.push({
          label: "Durchschnitt",
          data: filtered.map((entry) => ({
            x: new Date(entry.t).getTime(),
            y: entry.g || 0,
          })),
          borderColor: chartColors.littwinBlue.line,
          backgroundColor: chartColors.littwinBlue.background,
          tension: 0.1,
          fill: false,
          order: 2,
        });
      }

      if (hasCurrent) {
        datasets.push({
          label: "Messwert",
          data: filtered.map((entry) => ({
            x: new Date(entry.t).getTime(),
            y: entry.m || 0,
          })),
          borderColor: chartColors.littwinBlue.line,
          backgroundColor: chartColors.littwinBlue.background,
          tension: 0.1,
          fill: false,
          order: 2,
        });
      }

      const newChartData: ChartData<"line"> = {
        labels: [],
        datasets: datasets,
      };

      console.log("Chart datasets:", datasets.length, "lines");
      setChartData(newChartData);
      setShouldUpdateChart(false); // Reset flag
    } else if (shouldUpdateChart && (!reduxData || reduxData.length === 0)) {
      console.log("No Redux data available");
      setChartData({ datasets: [] });
      setShouldUpdateChart(false); // Reset flag
    }
  }, [
    reduxData,
    selectedKey,
    shouldUpdateChart,
    pickerVonDatum,
    pickerBisDatum,
  ]);

  if (!isOpen || !selectedKey) return null;

  // Prüfen ob Chart Daten haben (für cursor-wait)
  const hasChartData = chartData.datasets && chartData.datasets.length > 0;

  return (
    <div
      className={`fixed inset-0 bg-black bg-opacity-40 flex items-center justify-center z-50 ${
        !hasChartData ? "cursor-wait" : ""
      }`}
    >
      <div
        role="dialog"
        aria-modal="true"
        className={`bg-[var(--color-surface)] text-fg border border-base rounded-xl shadow-xl flex flex-col overflow-hidden transition-all duration-300 ${
          isFullScreen
            ? "w-[90vw] h-[90vh]"
            : "w-[70rem] max-w-[95vw] h-[40rem]"
        } ${!hasChartData ? "cursor-wait" : ""}`}
      >
        {/* Header */}
        <header className="flex items-center justify-between px-6 py-4 border-b border-base select-none bg-[var(--color-surface)]">
          <h2 className="text-base font-bold tracking-wide">
            Detailansicht: {selectedKey}
          </h2>
          <div className="flex items-center gap-3 text-lg">
            <button
              onClick={toggleFullScreen}
              className="icon-btn text-[1.4rem] hover:text-fg transition"
              aria-label={isFullScreen ? "Vollbild verlassen" : "Vollbild"}
              type="button"
            >
              <i
                className={
                  isFullScreen
                    ? "bi bi-fullscreen-exit"
                    : "bi bi-arrows-fullscreen"
                }
              />
            </button>
            <button
              onClick={handleClose}
              className="icon-btn text-[1.4rem]  transition"
              aria-label="Modal schließen"
              type="button"
            >
              <i className="bi bi-x-circle-fill" />
            </button>
          </div>
        </header>

        {/* Body */}
        <div className="flex-1 min-h-0 flex flex-col px-6 pt-4 pb-5 bg-[var(--color-surface)] overflow-hidden">
          <div className="mb-3">
            <SystemChartActionBar
              zeitraum={zeitraum}
              setZeitraum={setZeitraum}
              onFetchData={handleFetchData}
              isLoading={isLoading}
              className="mb-0"
            />
          </div>
          <div className="flex-1 min-h-0 rounded-lg border border-base bg-[var(--color-surface-alt)] px-3 py-2 shadow-inner">
            <Line ref={chartRef} data={chartData} options={chartOptions} />
          </div>
        </div>
        {/* Optional Footer (currently empty, reserved for future) */}
      </div>
    </div>
  );
};
