import { Fragment, useEffect, useMemo, useReducer, useState } from 'react';
import { useTranslation } from 'react-i18next';

import Breadcrumbs from '@design-system/Breadcrumbs';
import ButtonGroup from '@design-system/ButtonGroup';
import CardContainer from '@design-system/CardContainer';
import Table from '@design-system/Table';
import TableBody from '@design-system/Table/components/TableBody';
import TableCell from '@design-system/Table/components/TableCell';
import TableContainer from '@design-system/Table/components/TableContainer';
import TableHead from '@design-system/Table/components/TableHead';
import TableRow from '@design-system/Table/components/TableRow';
import Title from '@design-system/Title';
import { Stack, useTheme } from '@mui/material';
import i18next from 'i18next';
import { compact, concat, times } from 'lodash';

import DropdownList from '../DropdownList';
import TableRowSkeleton from '../TableRowSkeleton';
import {
  DataSource,
  type DropdownOptionItem,
  type HeatmapFilters,
  type HeatmapScoresResData,
  type HeatmapStats,
  type HeatmapTotalResData,
  ScoreType,
  SegmentType,
} from '../types';

import {
  HeatmapHeaderCell,
  HeatScoreCell,
  ScoreTypeLegend,
} from './components';
import { filtersReducer, isBossSegment, isTotalColumn } from './utils';

const COLUMNS_LENGTH = 5;

type HeatmapProps = {
  totalsData: HeatmapTotalResData | undefined;
  scoresData: HeatmapScoresResData | undefined;
  SegmentSelect: (props: {
    onChange: (value: HeatmapFilters['segment']) => void;
    value: HeatmapFilters['segment'];
  }) => JSX.Element;
  onFiltersChange: (nextFilters: HeatmapFilters) => void;
  defaultFilters: HeatmapFilters;
  loading?: boolean;
  scoreSelectDisabled?: boolean;
  restrictToParentId?: number;
};

const Heatmap = ({
  totalsData,
  scoresData,
  loading,
  SegmentSelect,
  onFiltersChange,
  defaultFilters,
  scoreSelectDisabled = false,
  restrictToParentId,
}: HeatmapProps) => {
  const { t } = useTranslation('material_hu_only');
  const theme = useTheme();

  const [filters, setFilters] = useReducer(filtersReducer, defaultFilters);
  const [managers, setManagers] = useState<HeatmapStats[]>([]);

  const breadcrumbHierarchy = totalsData?.hierarchy.filter(
    column => !isTotalColumn(column),
  );

  const restrictedParentIndex = useMemo(
    () =>
      breadcrumbHierarchy?.findIndex(
        column => column.id === restrictToParentId,
      ),
    [breadcrumbHierarchy, restrictToParentId],
  );

  const { segment, scoreType } = filters;
  const headerBorderColor = theme.palette.new.action.background.neutral.hover;
  const headerBorder = '2px solid';

  useEffect(() => {
    onFiltersChange(filters);
  }, [filters]);

  const handleChangeDataSource = (nextValue: DataSource) => {
    setFilters({
      dataSource: nextValue,
    });
  };

  const handleChangeScoreType = (nextValue: DropdownOptionItem<ScoreType>) => {
    setFilters({
      scoreType: nextValue,
    });
  };

  const handleChangeSegment = (nextValue: HeatmapFilters['segment']) => {
    setFilters({
      segment: nextValue,
    });

    if (isBossSegment(nextValue.id)) {
      setManagers([]);
      handleChangeParentId(null);
    }
  };

  const handleChangeParentId = (parentId: HeatmapFilters['parentId']) => {
    setFilters({
      parentId,
    });
  };

  const handleChangeParent = (column: HeatmapStats) => {
    if (segment.id === SegmentType.DIRECT_BOSS) {
      setManagers(prev => [...prev, column]);
    }
    handleChangeParentId(column.id);
  };

  const renderHeaderCell = ({
    column,
    isInHierarchy = false,
  }: {
    column: HeatmapStats;
    isInHierarchy?: boolean;
  }) => {
    const title = isTotalColumn(column)
      ? t('people_experience.total')
      : column.title;

    return (
      <HeatmapHeaderCell
        colSpan={2}
        key={column.id}
        sx={{
          borderTop: headerBorder,
          borderColor:
            isInHierarchy && !isTotalColumn(column)
              ? 'primary.main'
              : headerBorderColor,
          backgroundColor: 'inherit',
        }}
        align={isTotalColumn(column) ? 'center' : 'left'}
        title={title}
        subtitle={column.subtitle}
        participantsAmount={
          isTotalColumn(column) ? null : column.participantsAmount
        }
        onClick={
          column.hasChildren && !isTotalColumn(column)
            ? () => handleChangeParent(column)
            : undefined
        }
      />
    );
  };

  const baseBredcrumbProps = {
    href: undefined,
    component: 'button',
  } as const;

  const isColumnAccessible = (index: number) =>
    restrictToParentId
      ? !!restrictedParentIndex && index >= restrictedParentIndex
      : true;

  const breadcrumbLinks = compact(
    concat(
      isBossSegment(segment.id) && {
        title: segment.name,
        ...baseBredcrumbProps,
        isPresentational:
          !!restrictToParentId && segment.id === SegmentType.BOSSES,
        onClick: () => {
          handleChangeParentId(null);
          setManagers([]);
        },
      },
      segment.id === SegmentType.BOSSES &&
        breadcrumbHierarchy?.map((column, index) => ({
          title: column.title,
          ...baseBredcrumbProps,
          onClick: () => handleChangeParentId(column.id),
          isPresentational: !isColumnAccessible(index),
        })),
      segment.id === SegmentType.DIRECT_BOSS &&
        managers.map((manager, index) => ({
          title: manager.title,
          ...baseBredcrumbProps,
          onClick: () => {
            handleChangeParentId(manager.id);
            setManagers(prev => prev.slice(0, index + 1));
          },
          isPresentational: false,
        })),
    ),
  );

  return (
    <Stack sx={{ gap: 3, flex: '1 1 0%', minHeight: 0 }}>
      <Stack
        sx={{
          flexDirection: 'row',
          p: 2,
          alignItems: 'center',
          gap: 2,
          borderRadius: theme.shape.borderRadiusM,
          border: `1px solid ${theme.palette.new.border.neutral.default}`,
          backgroundColor: theme.palette.new.background.elements.default,
        }}
      >
        <Stack
          sx={{
            flex: 1,
            flexDirection: 'row',
            gap: 2,
            alignItems: 'center',
          }}
        >
          <ButtonGroup
            labels={[
              t('people_experience.dimensions'),
              t('people_experience.questions'),
            ]}
            onChange={index => {
              if (index === 0) {
                handleChangeDataSource(DataSource.TOPICS);
              } else {
                handleChangeDataSource(DataSource.QUESTIONS);
              }
            }}
            fixedCheck
          />
          <DropdownList
            options={[
              {
                id: ScoreType.SCORE,
                name: i18next.t('people_experience.score', {
                  ns: 'material_hu_only',
                }),
              },
              {
                id: ScoreType.DIFFERENCE,
                name: i18next.t('people_experience.difference', {
                  ns: 'material_hu_only',
                }),
              },
            ]}
            value={scoreType}
            onChange={handleChangeScoreType}
            disabled={scoreSelectDisabled}
          />
        </Stack>
        <ScoreTypeLegend scoreTypeId={scoreType.id} />
      </Stack>
      <CardContainer
        fullWidth
        padding={0}
        sx={{
          flex: '1 1 0%',
          minHeight: 0,
          display: 'flex',
          flexDirection: 'column',
          overflowY: 'auto',
        }}
      >
        <Stack sx={{ flex: '1 1 0%', minHeight: 0, gap: 2, p: 2 }}>
          {breadcrumbLinks.length > 1 && (
            <Breadcrumbs links={breadcrumbLinks} />
          )}
          <TableContainer>
            <Table
              stickyHeader={!loading}
              aria-label={t('people_experience.alt_sticky_table')}
              sx={{ tableLayout: loading ? 'auto' : 'fixed' }}
            >
              {!loading && (
                <colgroup>
                  <col style={{ width: '300px' }} />
                  <col />
                  <col />
                  {totalsData?.hierarchy
                    .concat(totalsData?.stats)
                    ?.map(column => (
                      <Fragment key={column.id}>
                        <col style={{ width: '150px' }} />
                        <col />
                      </Fragment>
                    ))}
                </colgroup>
              )}
              <TableHead>
                {loading && (
                  <TableRowSkeleton
                    columnsLength={COLUMNS_LENGTH}
                    headerRow
                  />
                )}
                {!loading && (
                  <TableRow headerRow>
                    <TableCell
                      colSpan={3}
                      sx={{
                        borderTop: headerBorder,
                        borderColor: headerBorderColor,
                        backgroundColor: 'inherit',
                        position: 'sticky',
                        left: 0,
                        zIndex: 3,
                      }}
                    >
                      <SegmentSelect
                        value={segment}
                        onChange={handleChangeSegment}
                      />
                    </TableCell>
                    {totalsData?.hierarchy?.map(column =>
                      renderHeaderCell({
                        column,
                        isInHierarchy: true,
                      }),
                    )}
                    {totalsData?.stats?.map(column =>
                      renderHeaderCell({
                        column,
                      }),
                    )}
                  </TableRow>
                )}
              </TableHead>
              <TableBody>
                {loading &&
                  times(8, index => (
                    <TableRowSkeleton
                      columnsLength={COLUMNS_LENGTH}
                      key={index}
                    />
                  ))}
                {!loading && (
                  <>
                    <TableRow>
                      <TableCell
                        colSpan={3}
                        sx={{
                          position: 'sticky',
                          left: 0,
                          background:
                            theme.palette.new.background.elements.default,
                        }}
                      >
                        <Title
                          title={t('people_experience.survey_total')}
                          fontWeight="fontWeightRegular"
                          variant="S"
                        />
                      </TableCell>
                      {totalsData?.hierarchy
                        .concat(totalsData?.stats)
                        .map(stat => (
                          <HeatScoreCell
                            key={stat.id}
                            score={stat.result}
                            difference={stat.baseResultDifference}
                            baseScore={stat.baseResult}
                            scoreType={scoreType.id}
                            isTotal
                          />
                        ))}
                    </TableRow>
                    {scoresData?.hierarchy.map((hierarchyStat, rowIndex) => (
                      <TableRow key={hierarchyStat.id}>
                        <TableCell
                          colSpan={3}
                          sx={{
                            position: 'sticky',
                            left: 0,
                            backgroundColor:
                              theme.palette.new.background.elements.default,
                          }}
                        >
                          <Title
                            title={hierarchyStat.title}
                            copetin={hierarchyStat.subtitle}
                            variant="S"
                            withEllipsis
                            overflow="tooltip"
                            fontWeight="fontWeightRegular"
                          />
                        </TableCell>
                        {hierarchyStat.stats
                          .concat(scoresData?.stats[rowIndex].stats)
                          .map((child, columnIndex) => (
                            <HeatScoreCell
                              key={child.id ?? child.title}
                              score={child.result}
                              difference={child.baseResultDifference}
                              baseScore={child.baseResult}
                              scoreType={scoreType.id}
                              isTotal={
                                columnIndex === 0 || isTotalColumn(child)
                              }
                            />
                          ))}
                      </TableRow>
                    ))}
                  </>
                )}
              </TableBody>
            </Table>
          </TableContainer>
        </Stack>
      </CardContainer>
    </Stack>
  );
};

export default Heatmap;
