"use client";
// components/main/analogInputs/AnalogInputsChart.tsx
import React, { useEffect, useRef } from "react";
import { useDispatch, useSelector } from "react-redux";
import { RootState, AppDispatch } from "@/redux/store";
import { Line } from "react-chartjs-2";
import {
  Chart as ChartJS,
  LineElement,
  PointElement,
  CategoryScale,
  LinearScale,
  Tooltip,
  Legend,
  Filler,
  TimeScale,
  TooltipItem,
} from "chart.js";
import "chartjs-adapter-date-fns";
import { de } from "date-fns/locale";
import { getAnalogInputsHistoryThunk } from "@/redux/thunks/getAnalogInputsHistoryThunk";
import {
  setVonDatum,
  setBisDatum,
  setZeitraum,
  setAutoLoad,
} from "@/redux/slices/analogInputs/analogInputsHistorySlice";
import DateRangePicker from "@/components/common/DateRangePicker";
import { Listbox } from "@headlessui/react";
import { getColor } from "@/utils/colors";

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

type AnalogInputHistoryPoint = {
  t: string;
  m?: number;
  i?: number;
  a?: number;
  g?: number;
};

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

  const dispatch = useDispatch<AppDispatch>();
  const chartRef = useRef<any>(null);

  const { zeitraum, vonDatum, bisDatum, data, autoLoad, selectedId } =
    useSelector((state: RootState) => state.analogInputsHistory);
  const selectedAnalogInput = useSelector(
    (state: RootState) => state.selectedAnalogInput
  );
  // ✅ Button-Klick → Fetch auslösen
  const handleFetchData = () => {
    if (!selectedAnalogInput?.id) return;

    // Sicherstellen, dass die neuesten Werte aus dem DateRangePicker verwendet werden
    const latestVonDatum = vonDatum || new Date().toISOString().slice(0, 10);
    const latestBisDatum = bisDatum || new Date().toISOString().slice(0, 10);

    dispatch(
      getAnalogInputsHistoryThunk({
        eingang: selectedAnalogInput.id,
        zeitraum,
        vonDatum: latestVonDatum,
        bisDatum: latestBisDatum,
      })
    );

    if (
      chartRef.current &&
      chartRef.current.options &&
      chartRef.current.options.scales &&
      chartRef.current.options.scales.x
    ) {
      const chart = chartRef.current;
      chart.options.scales.x.min = new Date(latestVonDatum).getTime();
      chart.options.scales.x.max = new Date(latestBisDatum).getTime();

      // Aktualisiere die Daten des Diagramms
      const chartKey = selectedAnalogInput?.id
        ? String(selectedAnalogInput.id + 99)
        : null;
      const inputData = chartKey ? data[chartKey] ?? [] : [];
      const filteredData = inputData.filter((point) => {
        const date = new Date(point.t);
        const from = new Date(latestVonDatum);
        const to = new Date(latestBisDatum);
        return (!from || date >= from) && (!to || date <= to);
      });

      chart.data.datasets = [
        {
          label: selectedAnalogInput?.label
            ? `Messwerteingang ${selectedAnalogInput.label}`
            : "Messwerte",
          data: filteredData.map((point) => ({
            x: new Date(point.t),
            y: point.m,
          })),
          fill: false,
          borderColor: getColor("littwin-blue"),
          backgroundColor: "rgba(59,130,246,0.3)",
          borderWidth: 2,
          pointRadius: 0,
          tension: 0.1,
        },
      ];

      chart.update("none");
    }
  };

  // ✅ Filtere Daten aus Redux
  const chartKey = selectedAnalogInput?.id
    ? String(selectedAnalogInput.id + 99)
    : null;
  const inputData = chartKey ? data[chartKey] ?? [] : [];
  // ✅ Zeitbereich anwenden (nur Anzeige gefiltert)
  const filteredData = inputData.filter((point) => {
    const date = new Date(point.t);
    const from = vonDatum ? new Date(vonDatum) : null;
    const to = bisDatum ? new Date(bisDatum) : null;

    return (!from || date >= from) && (!to || date <= to);
  });
  useEffect(() => {
    const today = new Date();
    const vor30Tagen = new Date(today);
    vor30Tagen.setDate(today.getDate() - 30);

    if (!vonDatum) dispatch(setVonDatum(vor30Tagen.toISOString().slice(0, 10)));
    if (!bisDatum) dispatch(setBisDatum(today.toISOString().slice(0, 10)));
  }, [dispatch, vonDatum, bisDatum]);

  const handleFetchChartData = () => {
    if (!selectedId) return;
    dispatch(
      getAnalogInputsHistoryThunk({
        eingang: selectedId,
        zeitraum,
        vonDatum,
        bisDatum,
      })
    );
  };

  const dataKey = selectedId ? String(selectedId + 99) : null;
  let filteredPoints: AnalogInputHistoryPoint[] = [];
  if (dataKey && data[dataKey]) {
    const fromDate = vonDatum ? new Date(vonDatum) : null;
    const toDate = bisDatum ? new Date(bisDatum) : null;

    filteredPoints = data[dataKey].filter((p: AnalogInputHistoryPoint) => {
      const pointDate = new Date(p.t);
      return (
        (!fromDate || pointDate >= fromDate) && (!toDate || pointDate <= toDate)
      );
    });
  }
  const chartData = {
    datasets:
      filteredPoints.length > 0
        ? zeitraum === "DIA0"
          ? [
              {
                label: selectedAnalogInput?.label
                  ? `Messwert (m) ${selectedAnalogInput.label}`
                  : "Messwert (m)",
                data: filteredData
                  .filter((point) => typeof point.m === "number")
                  .map((point) => ({ x: new Date(point.t), y: point.m })),
                fill: false,
                borderColor: getColor("littwin-blue"),
                backgroundColor: "rgba(59,130,246,0.3)",
                borderWidth: 2,
                pointRadius: 0,
                tension: 0.1,
              },
              {
                label: "Minimum (i)",
                data: filteredData
                  .filter((point) => typeof point.i === "number")
                  .map((point) => ({ x: new Date(point.t), y: point.i })),
                fill: false,
                borderColor: "gray", // grau
                borderWidth: 1,
                pointRadius: 0,
                borderDash: [4, 2],
                tension: 0.1,
              },
              {
                label: "Maximum (a)",
                data: filteredData
                  .filter((point) => typeof point.a === "number")
                  .map((point) => ({ x: new Date(point.t), y: point.a })),
                fill: false,
                borderColor: "gray", // rot
                borderWidth: 1,
                pointRadius: 0,
                borderDash: [4, 2],
                tension: 0.1,
              },
            ]
          : [
              {
                label: "Minimum (i)",
                data: filteredData
                  .filter((point) => typeof point.i === "number")
                  .map((point) => ({ x: new Date(point.t), y: point.i })),
                fill: false,
                borderColor: "gray", // grün
                borderWidth: 1,
                pointRadius: 0,
                borderDash: [4, 2],
                tension: 0.1,
              },
              {
                label: "Maximum (a)",
                data: filteredData
                  .filter((point) => typeof point.a === "number")
                  .map((point) => ({ x: new Date(point.t), y: point.a })),
                fill: false,
                borderColor: "gray", // rot
                borderWidth: 1,
                pointRadius: 0,
                borderDash: [4, 2],
                tension: 0.1,
              },
              {
                label: "Durchschnitt (g)",
                data: filteredData
                  .filter((point) => typeof point.g === "number")
                  .map((point) => ({ x: new Date(point.t), y: point.g })),
                fill: false,
                borderColor: getColor("littwin-blue"),
                backgroundColor: "rgba(59,130,246,0.3)",
                borderWidth: 2,
                pointRadius: 0,
                tension: 0.1,
              },
            ]
        : [],
  };

  const chartOptions = {
    responsive: true,
    plugins: {
      legend: { position: "top" as const },
      tooltip: {
        mode: "index" as const,
        intersect: false,
        callbacks: {
          label: function (context: TooltipItem<"line">) {
            const label = context.dataset.label || "";
            return `${label}: ${context.parsed.y}`;
          },
          title: function (tooltipItems: TooltipItem<"line">[]) {
            const date = tooltipItems[0].parsed.x;
            return `Zeitpunkt: ${new Date(date).toLocaleString("de-DE")}`;
          },
        },
      },
      title: {
        display: true,
        text: selectedAnalogInput?.label
          ? `Verlauf: ${selectedAnalogInput.label}`
          : "Messwert-Verlauf",
      },
      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" },
        // ✅ Hier definieren wir den sichtbaren Bereich dynamisch
        min: vonDatum ? new Date(vonDatum).getTime() : undefined,
        max: bisDatum ? new Date(bisDatum).getTime() : undefined,
      },
      y: {
        title: {
          display: true,
          text: `Messwert ${selectedAnalogInput?.unit || ""}`,
        },
      },
    },
  };
  // ✅ DateRangePicker Event → Redux-Datum setzen (aber KEIN Fetch!)
  const handleDateChange = (from: string, to: string) => {
    dispatch(setVonDatum(from));
    dispatch(setBisDatum(to));
  };
  useEffect(() => {
    if (autoLoad && selectedId) {
      dispatch(
        getAnalogInputsHistoryThunk({
          eingang: selectedId,
          zeitraum,
          vonDatum,
          bisDatum,
        })
      );
      dispatch(setAutoLoad(false)); // ✅ zurücksetzen, sonst endlose Schleife
    }
  }, [autoLoad, selectedId, dispatch, zeitraum, vonDatum, bisDatum]);

  return (
    <div className="flex flex-col gap-3">
      <div className="flex flex-wrap items-center gap-4 mb-2">
        <DateRangePicker />

        <Listbox value={zeitraum} onChange={(v) => dispatch(setZeitraum(v))}>
          <div className="relative w-48">
            <Listbox.Button className="w-full border px-3 py-1 rounded bg-white flex justify-between items-center text-sm">
              <span>
                {zeitraum === "DIA0"
                  ? "Alle Messwerte"
                  : zeitraum === "DIA1"
                  ? "Stündlich"
                  : "Täglich"}
              </span>
              <i className="bi bi-chevron-down text-gray-400" />
            </Listbox.Button>
            <Listbox.Options className="absolute z-10 mt-1 w-full border bg-white shadow rounded text-sm">
              {["DIA0", "DIA1", "DIA2"].map((option) => (
                <Listbox.Option
                  key={option}
                  value={option}
                  className="px-4 py-1 cursor-pointer hover:bg-gray-200"
                >
                  {option === "DIA0"
                    ? "Alle Messwerte"
                    : option === "DIA1"
                    ? "Stündlich"
                    : "Täglich"}
                </Listbox.Option>
              ))}
            </Listbox.Options>
          </div>
        </Listbox>

        <button
          onClick={handleFetchData}
          className="px-4 py-1 bg-littwin-blue text-white rounded text-sm"
        >
          Daten laden
        </button>
      </div>

      <div className="h-[50vh] w-full">
        <Line ref={chartRef} data={chartData} options={chartOptions} />
      </div>
    </div>
  );
}
