import React, { memo, useCallback, useEffect, useState } from 'react';
import { Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts';
import type { Margin } from 'recharts/types/util/types';

import { useTheme } from '@mui/material/styles';
import { useTick, formatterData, setDomainCalc, fixChartsClasses } from '../../utils';
import type { ChartTooltipProps, ValueType, NameType } from '../../utils';
import type { Theme } from '../@styles/theme-provider';
import { CustomTooltip } from './CustomTooltip';
import type { CustomTooltipProps } from './CustomTooltip';

export interface ChartBarStackedProps {
  data: Record<NameType, Array<Record<NameType, ValueType>>>;
  tooltip?: boolean;
  tooltipProps?: Partial<ChartTooltipProps>;
  height?: number;
  domainMax?: number;
  domainCalc?: boolean;
  tickCountY?: number;
  dataKeyX?: CustomTooltipProps['format'];
  dynamicNamedData?: {
    dataName: string;
    percentValue: string;
    value: string;
  };
  chartMargin?: Margin;
}

const ChartBarStacked = (props: ChartBarStackedProps) => {
  const theme = useTheme<Theme>();
  const {
    data = {},
    tooltip,
    tooltipProps,
    height,
    domainMax = 100,
    domainCalc = false,
    tickCountY,
    dataKeyX = 'name',
    dynamicNamedData = {
      dataName: 'appVersion',
      percentValue: 'percentage',
      value: 'count'
    },
    chartMargin = { left: -24, right: 6 }
  } = props;

  const classes = fixChartsClasses();

  const [uniqKeys, setUniqKeys] = useState<string[]>([]);

  const [arrColorNew, setArrColorNew] = useState<{ color?: string; isLast: boolean }[]>([]); // to check colors output

  const [chartDataSet, setChartDataSet] = useState<Record<string, string | number | undefined>[]>(
    []
  );

  useEffect(() => {
    const sysNames = Object.keys(data);

    const tempChartData: Record<string, string | number | undefined>[] = [];

    sysNames.forEach((item: string, ind) => {
      tempChartData.push({ name: item });
      data[item].forEach(ver => {
        const title = `${item}_!${ver[dynamicNamedData.dataName]}`;
        tempChartData[ind][title] = ver[dynamicNamedData.percentValue];
      });
    });

    const arr: string[] = [];
    const arrColor: string[] = [];
    tempChartData.forEach(bar => {
      const keys = Object.keys(bar);
      keys.splice(keys.indexOf('name'), 1);

      for (let i = 0; i < keys.length; i += 1) {
        const temp = i % 16;
        arrColor.push(theme.palette.specialColors[temp]);
      }
      arr.push(...keys);
    });
    setUniqKeys(arr);
    const arrNew: { color?: string; isLast: boolean }[] = [];
    sysNames.forEach(item => {
      data[item].forEach((elem, index: number) => {
        arrNew.push({
          color: theme.palette.specialColors[index + 1 < 16 ? index + 1 : (index % 16) + 1],
          isLast: data[item].length === index + 1
        });
      });
    });

    setArrColorNew(arrNew);

    arr.forEach(item => {
      const indices = [];
      const element = item;
      let idx = arr.indexOf(element);
      while (idx !== -1) {
        indices.push(idx);
        idx = arr.indexOf(element, idx + 1);
      }
      for (let i = 1; i < indices.length; i += 1) {
        arrColor.splice(indices[i], 1);
      }
    });

    sysNames.forEach((item, ind) => {
      data[item].forEach(ver => {
        const title = `${item}_!${ver[dynamicNamedData.dataName]}`;
        tempChartData[ind][`${title}-count`] = ver[dynamicNamedData.value];
      });
    });
    setChartDataSet(tempChartData);
  }, [data, dynamicNamedData, theme.palette.specialColors]);

  const horizontalTick = {
    fontSize: theme.typography.caption1.fontSize,
    fill: theme.palette.primary[600],
    fontFamily: 'Inter'
  };

  const tick = useTick();

  const formatter = useCallback((value: string) => formatterData(value, dataKeyX), [dataKeyX]);
  const setDomain = useCallback(
    (dataMax: number | undefined) => setDomainCalc(dataMax, domainCalc, domainMax),
    [domainMax, domainCalc]
  );

  return (
    <ResponsiveContainer width="100%" height={height} className={classes.root}>
      <BarChart data={chartDataSet} margin={chartMargin}>
        <CartesianGrid vertical={false} stroke={theme.palette.primary[300]} strokeDasharray="2 2" />
        <XAxis
          dataKey={dataKeyX}
          tick={horizontalTick}
          axisLine={false}
          tickLine={false}
          minTickGap={1}
          tickFormatter={formatter}
          tickMargin={8}
        />
        <YAxis
          tickCount={tickCountY}
          scale="linear"
          domain={[0, setDomain]}
          tick={tick}
          axisLine={false}
          tickLine={false}
          minTickGap={1}
          tickMargin={2}
          padding={{ top: 8 }}
        />
        {tooltip && (
          <Tooltip
            cursor={{ fill: theme.palette.chart.tooltipHover }}
            content={
              <CustomTooltip format={dataKeyX} showTitleValue={tooltipProps?.withTitleValue} />
            }
            {...tooltipProps}
          />
        )}
        {uniqKeys?.map((entry, index) => (
          <Bar
            key={`cell-${entry}`}
            type="monotone"
            dataKey={entry}
            fill={arrColorNew[index].color}
            strokeWidth={2}
            fillOpacity={1}
            barSize={40}
            stackId="a"
            radius={[arrColorNew[index].isLast ? 4 : 0, arrColorNew[index].isLast ? 4 : 0, 0, 0]}
          />
        ))}
      </BarChart>
    </ResponsiveContainer>
  );
};

ChartBarStacked.defaultProps = {
  data: [],
  tooltip: true,
  height: 325,
  dataKeyX: 'date',
  domainCalc: false,
  domainMax: 100,
  tickCountY: 10,
  dynamicNamedData: {
    dataName: 'appVersion',
    percentValue: 'percentage',
    value: 'count'
  }
};

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