import React, { memo, useMemo } from 'react';
import cloneDeep from 'lodash/cloneDeep';
import { Cell, Pie, PieChart as RePieChart, Tooltip } from 'recharts';

import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid';
import Typography from '@mui/material/Typography';
import { useTheme } from '@mui/material/styles';

import { CustomTooltip } from './CustomTooltip';
import createClasses from './styles';
import type { DonutProps } from './types';

const Donut = (props: DonutProps) => {
  const { title = '', subtitle, size, half, data = [], tooltip, tooltipPostfix } = props;
  const classes = createClasses({ size, title });

  const theme = useTheme();

  const [chartWidth, lineWidth] = useMemo(() => {
    // here the 88, 120 and 160 are widths of all variants of donuts, and
    // 2 added for correct view (if we didn't add it the donut will be cut)
    switch (size) {
      case 'xsmall':
        return [88 + 2, 5];

      case 'small':
      default:
        return [128 + 2, 8];

      case 'large':
        return [160 + 2, 8];
    }
  }, [size]);

  const chartHeight = chartWidth / (half ? 2 : 1); // chartHeight - it calculated because if we need to use half donut we need only half of height
  const outerRadius = (chartWidth - 2) / 2; // here hardcoded "- 2" for correct size because we added in chartWidth 2
  const innerRadius = outerRadius - lineWidth; // subtract the thickness of the donut line
  const margin = half ? chartHeight - 1 : 0; // it need for half donut correct position
  const textPosition = half ? 'flex-end' : 'center'; // this is for text position, because it not the same for donut and half donut
  const newData = useMemo(() => {
    // these calculations are done because in the design of the chart we use rounding
    // and they close the visibility of the empty option if it is small, for example 49 is filled in and 1 is empty
    const tempArr = cloneDeep(data);

    const index = tempArr.findIndex(item => item.name === 'Empty');
    if (index > -1) {
      tempArr[index].color = theme.palette.secondary[200];
    }

    if (
      tempArr.length === 2 &&
      tempArr[1].name === 'Empty' &&
      tempArr[1].value !== 0 &&
      tempArr[0].value >= 40
    ) {
      const stepValue = +(tempArr[0].value / 40).toFixed(0) + 1;
      tempArr[1].value = stepValue > tempArr[1].value ? stepValue : data[1].value;
    }

    return [...tempArr].reverse();
  }, [data, theme.palette.secondary]);

  return (
    <Box position="relative" display="inline-block">
      <Grid container direction="column" justifyContent={textPosition} alignItems="center">
        {(title || subtitle) && (
          <Grid container direction="column" className={classes.textContainer}>
            {title && (
              <Typography component="span" className={classes.title}>
                {title}
              </Typography>
            )}
            {subtitle && (
              <Typography component="span" className={classes.subtitle}>
                {subtitle}
              </Typography>
            )}
          </Grid>
        )}
        <RePieChart width={chartWidth} height={chartHeight} margin={{ top: margin }}>
          <Pie
            data={newData}
            startAngle={half ? 0 : -267} // here we use angles "-267" and in next line "93" it is needed for correct display of roundings line
            endAngle={half ? 180 : 93}
            outerRadius={outerRadius}
            innerRadius={innerRadius}
            blendStroke
            dataKey="value"
            cornerRadius={15}
            paddingAngle={-4}
          >
            {newData?.map((entry, index) => (
              <Cell
                key={`cell-${entry.name}`}
                fill={entry.color ? entry.color : theme.palette.specialColors[index + 1]}
              />
            ))}
          </Pie>
          {tooltip && (
            <Tooltip
              content={<CustomTooltip tooltipPostfix={tooltipPostfix} />}
              position={{ y: half ? 10 : undefined }}
            />
          )}
        </RePieChart>
      </Grid>
    </Box>
  );
};

Donut.defaultProps = {
  size: 'small',
  data: [
    {
      name: 'Empty',
      value: 10,
      color: '#E5EAF6'
    }
  ],
  half: false,
  tooltip: false
};

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