import React, { useEffect, useRef } from 'react';
import type { ScatterDataPoint } from 'chart.js';
import {
  CategoryScale,
  Chart,
  Filler,
  LinearScale,
  LineController,
  LineElement,
  PointElement,
  TimeScale,
  Tooltip,
} from 'chart.js';

import 'chartjs-adapter-moment';

import { tailwindConfig } from '../../utils';

Chart.register(
  Filler,
  Tooltip,
  TimeScale,
  LineElement,
  LinearScale,
  PointElement,
  CategoryScale,
  LineController
);

interface ILineChartProps {
  data: any;
  width: number;
  height: number;
  total?: number | string;
}

const LineChart = ({
  data,
  width,
  height,
  total,
}: ILineChartProps): JSX.Element => {
  const canvas: React.MutableRefObject<any> = useRef<any>(null);
  const legend: React.MutableRefObject<any> = useRef<any>(null);

  useEffect(() => {
    const ctx: any = window && canvas?.current;
    const chart: Chart<
      'line',
      (number | ScatterDataPoint | null)[],
      unknown
    > | null = ctx
      ? new Chart(ctx, {
          type: 'line',
          data: data,
          options: {
            layout: { padding: 20 },
            scales: {
              y: {
                beginAtZero: true,
                grid: { display: false },
                ticks: { maxTicksLimit: 7, callback: value => `${value}` },
              },
              x: {
                grid: { display: false },
                ticks: { autoSkipPadding: 48, maxRotation: 0 },
              },
            },
            plugins: {
              legend: { display: false },
              tooltip: {
                callbacks: { label: context => `${context.parsed.y}` },
              },
            },
            interaction: { intersect: false, mode: 'nearest' },
            maintainAspectRatio: false,
            // resizeDelay: 200, // fix breaking error
          },
          plugins: [
            {
              id: 'htmlLegend',
              afterUpdate(c) {
                const ul = legend.current;
                if (!ul) return;
                // Remove old legend items
                while (ul.firstChild) {
                  ul.firstChild.remove();
                }
                // Reuse the built-in legendItems generator

                if (c?.options.plugins?.legend?.labels?.generateLabels) {
                  const items =
                    c?.options?.plugins?.legend?.labels?.generateLabels(c);
                  items.forEach(item => {
                    const li = document?.createElement('li');
                    li.style.marginLeft = tailwindConfig().theme.margin[3];
                    // Button element
                    const button = document?.createElement('button');
                    button.style.display = 'inline-flex';
                    button.style.alignItems = 'center';
                    button.style.opacity = item.hidden ? '.3' : '';
                    button.onclick = () => {
                      c?.setDatasetVisibility(
                        item.datasetIndex || 0,
                        !c?.isDatasetVisible(item.datasetIndex || 0)
                      );
                      c?.update();
                    };
                    // Color box
                    const box = document?.createElement('span');
                    box.style.display = 'block';
                    box.style.width = tailwindConfig().theme.width[3];
                    box.style.height = tailwindConfig().theme.height[3];
                    box.style.borderRadius =
                      tailwindConfig().theme.borderRadius.full;
                    box.style.marginRight = tailwindConfig().theme.margin[2];
                    box.style.borderWidth = '3px';
                    box.style.borderColor =
                      tailwindConfig().theme.colors.indigo[500];
                    box.style.pointerEvents = 'none';
                    const label = document?.createElement('span');
                    label.style.color =
                      tailwindConfig().theme.colors.slate[500];
                    label.style.fontSize =
                      tailwindConfig().theme.fontSize.sm[0];
                    label.style.lineHeight =
                      tailwindConfig().theme.fontSize.sm[1].lineHeight;
                    const labelText = document?.createTextNode(item.text);
                    label.appendChild(labelText);
                    li.appendChild(button);
                    button.appendChild(box);
                    button.appendChild(label);
                    ul.appendChild(li);
                  });
                }
              },
            },
          ],
        })
      : null;

    return () => chart?.destroy();
  }, []);

  return (
    <React.Fragment>
      {total ? (
        <div className="w-full">
          <div className="flex flex-wrap justify-between items-end">
            <div className="flex items-center">
              <div className="text-slate-800">
                <p className="font-extrabold text-xl">
                  {Number(total).toLocaleString(undefined, {
                    minimumFractionDigits: 2,
                    maximumFractionDigits: 2,
                  })}
                </p>
              </div>
              <div className="text-sm"></div>
            </div>
            <div className="grow ml-2 mb-1">
              <ul ref={legend} className="flex flex-wrap justify-end" />
            </div>
          </div>
        </div>
      ) : null}

      {/* Chart built with Chart.js 3 */}
      <div className="grow w-full h-44">
        <canvas ref={canvas} width={width} height={height}></canvas>
      </div>
    </React.Fragment>
  );
};

export default LineChart;
