import React, { memo, useCallback, useMemo } from 'react';
import {
  CartesianGrid,
  Line,
  LineChart,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis
} from 'recharts';
import type { Margin } from 'recharts/types/util/types';
import { useTheme } from '@mui/material/styles';

import {
  useEmpty,
  useTick,
  ChartTooltip,
  formatterData,
  setDomainCalc,
  fixChartsClasses
} from '../../utils';
import type { ChartTooltipProps } from '../../utils';
import type { Theme } from '../@styles/theme-provider';

export interface ChartLineProps {
  data?: Record<string, string | number | undefined>[];
  tooltip?: boolean;
  height?: number;
  dots?: boolean;
  domainMax?: number;
  domainCalc?: boolean;
  tickCountY?: number;
  dataKeyX?: ChartTooltipProps['format'];
  dataXFormat?: ChartTooltipProps['dataXFormat'];
  dataYFormat?: ChartTooltipProps['dataYFormat'];
  tooltipFormatter?: ChartTooltipProps['tooltipFormatter'];
  chartConfig?: ChartTooltipProps['config'];
  chartMargin?: Margin;
}

const ChartLine = (props: ChartLineProps) => {
  const theme = useTheme<Theme>();
  const empty = useEmpty();
  const {
    data = [],
    tooltip,
    height,
    dots,
    domainMax = 100,
    domainCalc = false,
    tickCountY,
    dataKeyX = 'date',
    dataXFormat = 'month',
    dataYFormat = '',
    tooltipFormatter,
    chartConfig = [empty],
    chartMargin = { left: -24, right: 6 }
  } = props;

  const classes = fixChartsClasses();

  const tick = useTick();
  const newConfig = useMemo(() => [...chartConfig].reverse(), [chartConfig]);
  const formatterX = useCallback(
    (value: string) => formatterData(value, dataKeyX, dataXFormat),
    [dataKeyX, dataXFormat]
  );
  const formatterY = useCallback(
    (value: string) => formatterData(value, '', dataYFormat),
    [dataYFormat]
  );
  const setDomain = useCallback(
    (dataMax: number | undefined) => setDomainCalc(dataMax, domainCalc, domainMax),
    [domainMax, domainCalc]
  );

  return (
    <ResponsiveContainer width="100%" height={height} className={classes.root}>
      <LineChart data={data} margin={chartMargin}>
        <CartesianGrid vertical={false} stroke={theme.palette.primary[300]} strokeDasharray="2 2" />
        <XAxis
          dataKey={dataKeyX}
          tick={tick}
          axisLine={false}
          tickLine={false}
          tickCount={data.length}
          minTickGap={1}
          tickFormatter={formatterX}
          tickMargin={8}
        />
        <YAxis
          tickCount={tickCountY}
          scale="linear"
          domain={[0, setDomain]}
          tick={tick}
          axisLine={false}
          tickLine={false}
          minTickGap={1}
          tickFormatter={formatterY}
          tickMargin={2}
          padding={{ top: 8 }}
        />
        {tooltip && (
          <Tooltip
            content={
              <ChartTooltip
                format={dataKeyX}
                dataXFormat={dataXFormat}
                dataYFormat={dataYFormat}
                tooltipFormatter={tooltipFormatter}
                config={newConfig}
              />
            }
          />
        )}
        {newConfig?.map(
          (entry, index) =>
            entry.show && (
              <Line
                key={`cell-${entry.id}`}
                type="monotone"
                dataKey={entry.id}
                stroke={entry.color || theme.palette.specialColors[newConfig.length - index]}
                strokeWidth={2}
                fillOpacity={1}
                dot={
                  dots
                    ? {
                        stroke:
                          entry.color || theme.palette.specialColors[newConfig.length - index],
                        strokeWidth: 2,
                        r: 3,
                        fill: theme.palette.common.white
                      }
                    : false
                }
                activeDot={{
                  stroke: entry.color || theme.palette.specialColors[newConfig.length - index],
                  strokeWidth: 2,
                  r: 5,
                  fill: theme.palette.common.white
                }}
                connectNulls
              />
            )
        )}
      </LineChart>
    </ResponsiveContainer>
  );
};

ChartLine.defaultProps = {
  data: [],
  chartConfig: [],
  tooltip: true,
  height: 325,
  dots: false,
  dataKeyX: 'date',
  domainCalc: false,
  domainMax: 100,
  tickCountY: 10,
  dataXFormat: 'month',
  dataYFormat: '',
  chartMargin: { left: -24, right: 6 }
};

const m = memo(ChartLine);
export { m as ChartLine };
