import { useState } from 'react';
import { useQuery } from 'react-query';
import { useOutletContext } from 'react-router-dom';

import { concat, isEmpty, negate } from 'lodash-es';
import { IconChartBar } from '@material-hu/icons/tabler';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import EnpsChart from '@material-hu/components/composed-components/peopleExperience/npsResults/components/EnpsChart';
import NavigableLabelTicks from '@material-hu/components/composed-components/peopleExperience/npsResults/components/NavigableLabelTicks';
import type * as PxTypes from '@material-hu/components/composed-components/peopleExperience/types';
import Breadcrumbs from '@material-hu/components/design-system/Breadcrumbs';
import StateCard from '@material-hu/components/design-system/StateCard';
import Title from '@material-hu/components/design-system/Title';

import { useAuth } from 'src/contexts/JWTContext';
import { getBaseSegments } from '../../../../../../constants';
import { pxKeys } from '../../../../../../queries';
import { roundNumber } from '../../../../../../utils/formatting';
import { makeBlacklistSegmentChecker } from '../../../../../../utils/segmentBlacklist';
import {
  getEnpsChart,
  getSegmentationGroups,
} from '../../../../../../services';
import {
  type EnpsChartParams,
  type EnpsSegment,
  type SegmentationFilterParams,
  type SegmentFilter,
  type TransformedManagerSurvey,
} from '../../../../../../types';
import { useLokaliseTranslation } from 'src/utils/i18n';

import SegmentSelect from '../SegmentSelect';

import { deriveParentIdFromSegment, getSegmentType } from './utils';

type BreadcrumbItem = {
  label: string;
  value: number | null;
};

type EnpsChartSectionProps = {
  surveyId: number;
  filters: SegmentationFilterParams;
  isLoadingScoreData: boolean;
};

const EnpsChartSection = ({
  surveyId,
  filters,
  isLoadingScoreData,
}: EnpsChartSectionProps) => {
  const { t } = useLokaliseTranslation('people_experience');
  const { survey } = useOutletContext<{ survey: TransformedManagerSurvey }>();
  const { instance } = useAuth();

  const [segmentFilter, setSegmentFilter] = useState<SegmentFilter>();
  const [parentId, setParentId] = useState<number | null>(null);
  const [breadcrumb, setBreadcrumb] = useState<BreadcrumbItem[]>([]);
  const [filteredBreadcrumb, setFilteredBreadcrumb] = useState<
    BreadcrumbItem[]
  >([]);

  const baseSegments = getBaseSegments(t);

  const isSegmentBlacklisted = makeBlacklistSegmentChecker({
    instanceId: instance!.id,
    surveyId: survey.id,
  });

  const { data: segmentOptions, isLoading: isLoadingSegments } = useQuery(
    pxKeys.segmentationGroups(survey.id),
    () => getSegmentationGroups({ surveyId: survey.id, page: 0, limit: 100 }),
    {
      select: response => {
        const allSegments = concat(
          baseSegments,
          response.data.items.map(segment => ({
            id: segment.id,
            title: segment.name,
            type: getSegmentType(segment.type as PxTypes.SegmentationGroupType),
          })),
        );

        const filteredSegments = allSegments.filter(
          segment => !isSegmentBlacklisted(segment.id),
        );

        return filteredSegments;
      },
      onSuccess: responseData => {
        if (!segmentFilter && responseData.length > 0) {
          const defaultSegment = responseData[0];
          const rootItem = { label: defaultSegment.title, value: null };
          setSegmentFilter(defaultSegment);
          setBreadcrumb([rootItem]);
          setFilteredBreadcrumb([rootItem]);
        }
      },
    },
  );

  const chartParams: EnpsChartParams = {
    surveyId,
    dimension: segmentFilter?.type,
    parentId: deriveParentIdFromSegment(segmentFilter, parentId),
    ...filters,
  };

  const { data: chartData, isLoading: isLoadingChartData } = useQuery(
    pxKeys.eNpsChart(chartParams),
    () => getEnpsChart(chartParams),
    {
      select: response => response.data,
      enabled: !!segmentFilter?.id,
      keepPreviousData: true,
      onSuccess: response => {
        response.hierarchy.forEach(stat => {
          if (!breadcrumb.map(b => b.value).includes(stat.id)) {
            handlePushBreadcrumb({ value: stat.id, label: stat.title });
          }
        });
      },
    },
  );

  const hasSegmentationFilters = Object.values(filters).some(negate(isEmpty));

  const npsParents = chartData?.hierarchy.map(({ parentId, ...rest }) => rest);

  const npsStats: EnpsSegment[] = chartData
    ? [...(npsParents ?? []), ...chartData.stats]
    : [];

  const chartDataFormatted = npsStats.map(stat => ({
    label: stat.title,
    value: stat.score !== null ? roundNumber(stat.score) : null,
  }));

  const differenceDataFormatted = hasSegmentationFilters
    ? npsStats.map(stat => ({
        label: stat.title,
        value: stat.baseScore !== null ? roundNumber(stat.baseScore) : null,
      }))
    : undefined;

  // Navigation handlers
  const handlePushBreadcrumb = (item: BreadcrumbItem) => {
    setBreadcrumb(prev => [...prev, item]);
  };

  const handlePushFilteredBreadcrumb = (item: BreadcrumbItem) => {
    setFilteredBreadcrumb(prev => [...prev, item]);
  };

  const handlePopBreadcrumb = (index: number, id: number | null) => {
    if (index < filteredBreadcrumb.length - 1) {
      setBreadcrumb(prev => prev.slice(0, index + 1));
      setFilteredBreadcrumb(prev => prev.slice(0, index + 1));
      setParentId(id);
    }
  };

  const handleChangeSegmentFilter = (newSegment: SegmentFilter) => {
    const rootItem = { label: newSegment.title, value: null };
    setBreadcrumb([rootItem]);
    setFilteredBreadcrumb([rootItem]);
    setParentId(null);
    setSegmentFilter(newSegment);
  };

  const handleDimensionClick = (title: string, id: number) => {
    setParentId(id);

    if (!id) {
      handlePopBreadcrumb(0, null);
      return;
    }

    const breadcrumbIds = breadcrumb.map(b => b.value);
    if (!breadcrumbIds.includes(id)) {
      handlePushBreadcrumb({ label: title, value: id });
    } else {
      const idx = npsStats.map(segment => segment.id).indexOf(id);
      if (idx >= 0 && idx < breadcrumbIds.length - 1) {
        handlePopBreadcrumb(idx, id);
      }
    }

    handlePushFilteredBreadcrumb({ label: title, value: id });
  };

  const canBeClicked = (stat: EnpsSegment) =>
    stat.hasChildren && !breadcrumb.map(item => item.value).includes(stat.id);

  // Transform npsStats to NavigableLegendFooter items
  const hierarchyLength = npsParents?.length ?? 0;
  const labelItems = npsStats.map((stat, index) => ({
    title: stat.id ? stat.title : t('TOTAL'),
    description: stat.id ? stat.subtitle : t('GLOBAL'),
    hasChildren: stat.hasChildren,
    passedThreshold: stat.passedThreshold,
    highlighted: index < hierarchyLength && index !== 0,
    onClick: canBeClicked(stat)
      ? () => handleDimensionClick(stat.title, stat.id)
      : undefined,
  }));

  return (
    <Stack
      sx={{
        flex: 1,
      }}
    >
      <EnpsChart
        data={chartDataFormatted}
        differenceData={differenceDataFormatted}
        loading={isLoadingChartData}
        emptyStateSlot={
          <StateCard
            title={t('survey.empty_state.filtered.title')}
            description={t('survey.empty_state.filtered.description')}
            icon={IconChartBar}
            variant="primary"
            sx={{
              height: 300,
            }}
          />
        }
        titleSlot={
          <Stack sx={{ flexDirection: 'row', alignItems: 'center', gap: 2 }}>
            <Typography variant="h6">{t('enps_by')}</Typography>
            <SegmentSelect
              value={segmentFilter}
              onChange={handleChangeSegmentFilter}
              disabled={isLoadingScoreData}
              options={segmentOptions ?? []}
              loading={isLoadingSegments}
            />
          </Stack>
        }
        headerSlot={
          filteredBreadcrumb.length > 1 ? (
            <Stack
              sx={{ flexDirection: 'row', alignItems: 'center', gap: 1, py: 2 }}
            >
              <Title title={`${t('enps_domain.chart_hierarchy_levels')}:`} />
              <Breadcrumbs
                links={filteredBreadcrumb.map(({ label }, index) => ({
                  title: label,
                  onClick:
                    index === filteredBreadcrumb.length - 1
                      ? undefined
                      : () =>
                          handlePopBreadcrumb(
                            index,
                            filteredBreadcrumb[index].value,
                          ),
                }))}
              />
            </Stack>
          ) : null
        }
        navigationSlot={<NavigableLabelTicks items={labelItems} />}
        nullDataMessage={t('not_enough_data_title')}
      />
    </Stack>
  );
};

export default EnpsChartSection;
