import Chart from 'react-apexcharts';
import { useQuery } from 'react-query';

import { truncate } from 'lodash-es';
import CircularProgress from '@material-hu/mui/CircularProgress';
import * as colors from '@material-hu/mui/colors';
import Stack from '@material-hu/mui/Stack';
import { type Theme, useTheme } from '@material-hu/mui/styles';

import PxScaleQuestionChart from '@material-hu/components/composed-components/peopleExperience/ScaleQuestionChart';

import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { getQuestionStats } from '../../services';
import {
  type CommentsFilter,
  type QuestionTemplate,
  QuestionTemplateType,
  type TransformedChoicesStats,
} from '../../types';
import { useLokaliseTranslation } from 'src/utils/i18n';

import { pxKeys } from '../../queries';
import EmptyState from '../EmptyState';

import { getVariantStyles } from './constants';
import { formatChoiceStat } from './utils';

type ChartFactoryProps = {
  type: QuestionTemplateType;
  formId: number;
  questionId: QuestionTemplate['id'];
  onSelectDatum: React.Dispatch<React.SetStateAction<CommentsFilter | null>>;
};

const getChartColors = (theme: Theme) => [
  colors.deepPurple[300],
  colors.deepPurple[500],
  colors.indigo[300],
  colors.indigo[600],
  colors.orange[500],
  colors.orange[900],
  theme.palette.new.graphics.error[500],
  theme.palette.new.graphics.error[900],
  colors.cyan[500],
  colors.cyan[800],
  theme.palette.new.graphics.teal[400],
  theme.palette.new.graphics.teal[700],
];

const QuestionAnswersChart = ({
  type,
  onSelectDatum,
  formId,
  questionId,
}: ChartFactoryProps) => {
  const theme = useTheme();
  const { t } = useLokaliseTranslation('people_experience');
  const HuGoThemeProvider = useHuGoTheme();

  const chartColors = getChartColors(theme);

  const params = { formId, questionId };

  const { data, isLoading } = useQuery(
    pxKeys.questionStats(params),
    () => getQuestionStats(params),
    {
      select: res => res.data,
      enabled: !!questionId,
    },
  );

  const hasDisplayData = !!data?.answersCount && data?.passedThreshold;

  const variantStyles = getVariantStyles(theme);

  const handleSelectDatum = (nextSelected: TransformedChoicesStats) => {
    onSelectDatum(prev => {
      if (prev !== null && nextSelected.idx === prev?.idx) {
        return null;
      } else {
        const { bgcolor, color } = variantStyles[nextSelected.type];
        return {
          idx: nextSelected.idx,
          value: { integerAnswer: nextSelected.value },
          label: nextSelected.label,
          foreColor: bgcolor,
          textColor: color,
        };
      }
    });
  };

  const stats = data?.stats ?? {};

  const noData = {
    text: t(isLoading ? 'LOADING' : 'NO_CHART_DATA'),
    style: {
      fontFamily: theme.typography.fontFamily,
    },
  };

  if (isLoading) {
    return (
      <Stack sx={{ alignItems: 'center', p: 4 }}>
        <CircularProgress />
      </Stack>
    );
  }

  if (!hasDisplayData) {
    return (
      <EmptyState
        title={t('NOT_ENOUGH_DATA_TITLE')}
        description={t('NOT_ENOUGH_DATA_DESCRIPTION')}
      />
    );
  }

  switch (type) {
    case QuestionTemplateType.CHECKBOX: {
      const labels = Object.keys(stats);
      return (
        <Stack sx={{ alignItems: 'center', height: '220px' }}>
          <Stack sx={{ width: '100%', maxWidth: '470px', height: '100%' }}>
            <Chart
              key="multiple-choice-chart"
              type="donut"
              options={{
                noData,
                chart: {
                  animations: {
                    speed: 250,
                  },
                  events: {
                    dataPointSelection: (_event, _chartContext, options) => {
                      const { dataPointIndex } = options;
                      onSelectDatum({
                        idx: dataPointIndex,
                        label: labels[dataPointIndex],
                        value: { stringAnswer: labels[dataPointIndex] },
                      });
                    },
                  },
                },
                labels,
                dataLabels: {
                  enabled: false,
                },
                colors: chartColors,
                legend: {
                  horizontalAlign: 'center',
                  position: 'right',
                  fontFamily: theme.typography.fontFamily,
                  fontSize: String(theme.typography.fontSize),
                  formatter: legendName => truncate(legendName, { length: 20 }),
                },
                plotOptions: {
                  pie: {
                    donut: {
                      size: '50%',
                    },
                  },
                },
                tooltip: {
                  fillSeriesColor: false,
                },
              }}
              series={Object.values(stats)}
              height="100%"
            />
          </Stack>
        </Stack>
      );
    }
    case QuestionTemplateType.MULTIPLE_CHOICE: {
      const labels = Object.keys(stats);
      return (
        <Stack sx={{ height: '220px', maxWidth: '470px', margin: 'auto' }}>
          <Chart
            key="unique-choice-chart"
            type="donut"
            options={{
              noData,
              chart: {
                animations: {
                  speed: 250,
                },
                events: {
                  dataPointSelection: (_event, _chartContext, options) => {
                    const { dataPointIndex } = options;
                    onSelectDatum({
                      idx: dataPointIndex,
                      label: labels[dataPointIndex],
                      value: { stringAnswer: labels[dataPointIndex] },
                    });
                  },
                },
              },
              labels,
              dataLabels: {
                enabled: false,
              },
              colors: chartColors,
              legend: {
                horizontalAlign: 'center',
                position: 'right',
                fontFamily: theme.typography.fontFamily,
                fontSize: String(theme.typography.fontSize),
                formatter: legendName => truncate(legendName, { length: 20 }),
              },
              plotOptions: {
                pie: {
                  donut: {
                    size: '50%',
                  },
                },
              },
              tooltip: {
                fillSeriesColor: false,
              },
            }}
            series={Object.values(stats)}
            height="100%"
          />
        </Stack>
      );
    }
    case QuestionTemplateType.TEXT: {
      const rangeWidth = Math.max(...Object.values(stats)) / chartColors.length;

      const rangedColors = chartColors.map((color, index) => ({
        from: rangeWidth * index,
        to: rangeWidth * (index + 1),
        color,
      }));

      return (
        <Stack sx={{ height: '400px', width: '700px', margin: 'auto' }}>
          <Chart
            key="treemap-chart"
            type="treemap"
            options={{
              noData,
              legend: {
                show: false,
              },
              chart: {
                toolbar: {
                  show: false,
                },
                fontFamily: theme.typography.fontFamily,
                animations: {
                  speed: 150,
                },
              },
              plotOptions: {
                treemap: {
                  colorScale: {
                    ranges: rangedColors,
                  },
                },
              },
            }}
            series={[
              {
                data: Object.entries(stats).map(([key, value]) => ({
                  x: key,
                  y: value,
                })),
              },
            ]}
            height="100%"
          />
        </Stack>
      );
    }
    case QuestionTemplateType.LIKERT: {
      return (
        <HuGoThemeProvider>
          <PxScaleQuestionChart
            data={
              data?.choicesStats?.map<TransformedChoicesStats>(
                formatChoiceStat,
              ) ?? []
            }
            onSelectItem={handleSelectDatum}
            helperText={t('chart_section_description')}
            noDataText={t('no_data')}
          />
        </HuGoThemeProvider>
      );
    }
    default:
      return null;
  }
};

export default QuestionAnswersChart;
