import "uplot/dist/uPlot.min.css";
import { useEffect, useRef } from "react";
import type { UiSeverity } from "../../types";

export interface LineChartProps {
  values?: number[];
  severity?: UiSeverity;
  label?: string;
}

export function LineChart({
  values = [],
  severity = "neutral",
  label = "Telemetry trend",
}: LineChartProps) {
  const chartElementRef = useRef<HTMLDivElement>(null);
  const valuesKey = values.join(",");

  useEffect(() => {
    const chartElement = chartElementRef.current;
    if (!chartElement) return;

    let chart: ChartInstance | null = null;
    let resizeObserver: ResizeObserver | null = null;
    let disposed = false;

    void import("uplot").then((module) => {
      if (disposed || !chartElementRef.current) return;

      const element = chartElementRef.current;
      chart = new module.default(chartOptions(element, severity), chartData(values), element);

      if (typeof ResizeObserver !== "undefined") {
        resizeObserver = new ResizeObserver(() => {
          chart?.setSize(chartSize(element));
        });
        resizeObserver.observe(element);
      }
    });

    return () => {
      disposed = true;
      resizeObserver?.disconnect();
      chart?.destroy();
    };
  }, [severity, valuesKey, values]);

  return (
    <div
      className="line-chart"
      data-chart-library="uplot"
      data-severity={severity}
      data-values={values.join(",")}
      role="img"
      aria-label={label}
    >
      <div ref={chartElementRef} className="line-chart__canvas" aria-hidden="true" />
    </div>
  );
}

type ChartInstance = {
  destroy(): void;
  setSize(size: { width: number; height: number }): void;
};

function chartData(values: number[]): import("uplot").AlignedData {
  const normalized = values.length ? values : [0, 0];
  return [
    normalized.map((_, index) => index),
    normalized.map((value) => Math.max(0, Number(value) || 0)),
  ];
}

function chartOptions(
  element: HTMLElement,
  severity: UiSeverity,
): import("uplot").Options {
  return {
    ...chartSize(element),
    cursor: { show: false },
    legend: { show: false },
    padding: [2, 0, 2, 0],
    scales: {
      x: { time: false },
      y: { auto: true },
    },
    axes: [{ show: false }, { show: false }],
    series: [
      {},
      {
        stroke: chartStroke(element, severity),
        width: 2,
        points: { show: false },
      },
    ],
  };
}

function chartSize(element?: HTMLElement): { width: number; height: number } {
  return {
    width: Math.max(80, Math.round(element?.clientWidth || 120)),
    height: Math.max(20, Math.round(element?.clientHeight || 24)),
  };
}

function chartStroke(element: HTMLElement, severity: UiSeverity): string {
  const styles = window.getComputedStyle(element.closest(".line-chart") || element);
  const currentColor = styles.color;
  if (currentColor) return currentColor;
  if (severity === "danger") return "#ff1744";
  if (severity === "warning") return "#ffb020";
  return "#d7ff00";
}
