import { useMemo } from 'react';

import Pill from '@design-system/Pills';
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 Tooltip from '@design-system/Tooltip';
import { useTheme } from '@mui/material';
import {
  IconChevronRight,
  IconInfoCircle,
  IconMessage2X,
} from '@tabler/icons-react';

import SatisfactionChart from '../SatifactionChart';
import SatisfactionTableContentSkeleton from '../SatisfactionTableContentSkeleton';
import ScoreDifferenceIndicator from '../ScoreDifferenceIndicator';

import {
  type DimensionDatum,
  type SatisfactionDimensionsTableProps,
  type TableColumn,
} from './types';

const SatisfactionDimensionsTable = ({
  dimensions,
  dimensionsCount,
  dimensionsHeading,
  scoreHeading,
  scoreDifferenceHeading,
  tooltipLabels,
  getTooltipTitle,
  distributionHeading,
  noAnswerLabel,
  noQuestionsLabel,
  onClickRow,
  slotProps = {},
  loading = false,
  loadingMore = false,
  differenceIndicatorMeta,
}: SatisfactionDimensionsTableProps) => {
  const theme = useTheme();

  const hasScoreDifference = useMemo(
    () => dimensions.some(dimension => dimension.scoreDifference !== null),
    [dimensions],
  );

  const renderScoreCell = (row: DimensionDatum) => {
    if (!row.hasThresholdPassed) {
      return (
        <Tooltip description={noAnswerLabel}>
          <IconMessage2X
            size={20}
            color={theme.palette.new.text.neutral.default}
          />
        </Tooltip>
      );
    } else if (!row.hasQuestions) {
      return (
        <Tooltip description={noQuestionsLabel}>
          <IconInfoCircle
            size={20}
            color={theme.palette.new.text.neutral.default}
          />
        </Tooltip>
      );
    } else {
      return (
        <Title
          title={row.score}
          variant="S"
          fontWeight="fontWeightRegular"
        />
      );
    }
  };

  const columns: TableColumn[] = useMemo(() => {
    const baseColumns: TableColumn[] = [
      {
        id: 'name',
        heading: (count: number) => `${dimensionsHeading} (${count})`,
        width: '50%',
        renderCell: (row: DimensionDatum) => (
          <Title
            title={row.name}
            description={row.questionsLabel}
            variant="S"
            fontWeight="fontWeightRegular"
          />
        ),
      },
      {
        id: 'score',
        heading: scoreHeading,
        renderCell: renderScoreCell,
      },
    ];

    if (hasScoreDifference) {
      baseColumns.push({
        id: 'scoreDifference',
        heading: scoreDifferenceHeading,
        renderCell: (row: DimensionDatum) => {
          if (
            row.score !== null &&
            row.scoreDifference !== null &&
            row.baseScore !== null
          ) {
            return (
              <ScoreDifferenceIndicator
                difference={row.scoreDifference}
                popoverMeta={{
                  scoreDifferenceDescription:
                    differenceIndicatorMeta.getScoreDifferenceDescription(row),
                  score: row.score,
                  baseScore: row.baseScore,
                  scoreLabel: differenceIndicatorMeta.scoreLabel,
                  baseScoreLabel: differenceIndicatorMeta.baseScoreLabel,
                  footerLabel: differenceIndicatorMeta.footerLabel,
                }}
              />
            );
          }
          return renderScoreCell(row);
        },
      });
    }

    baseColumns.push({
      id: 'distribution',
      heading: distributionHeading,
      width: '50%',
      renderCell: (row: DimensionDatum) => {
        if (!row.hasThresholdPassed) {
          return (
            <Pill
              label={noAnswerLabel}
              type="disabled"
              size="medium"
              hasIcon={false}
            />
          );
        }

        if (!row.hasQuestions) {
          return (
            <Pill
              label={noQuestionsLabel}
              type="disabled"
              size="medium"
              hasIcon={false}
            />
          );
        }

        if (
          [row.promoters, row.detractors, row.neutrals].every(
            value => value === 0,
          )
        ) {
          return '--';
        }

        return (
          <SatisfactionChart
            promoters={row.promoters}
            detractors={row.detractors}
            neutrals={row.neutrals}
            getTooltipTitle={(key, value) =>
              getTooltipTitle
                ? getTooltipTitle(key, value)
                : `${tooltipLabels[key]}: ${value}`
            }
          />
        );
      },
    });

    baseColumns.push({
      id: 'actions',
      heading: '',
      width: 24,
      renderCell: () => <IconChevronRight size={16} />,
    });

    return baseColumns;
  }, [
    dimensionsHeading,
    scoreHeading,
    scoreDifferenceHeading,
    hasScoreDifference,
    distributionHeading,
    noAnswerLabel,
    noQuestionsLabel,
    tooltipLabels,
    getTooltipTitle,
    onClickRow,
    differenceIndicatorMeta,
    theme,
  ]);

  const handleRowClick = (question: DimensionDatum) => () => {
    const selection = window.getSelection();
    if (selection && selection.type === 'Range' && selection.toString()) {
      return;
    }
    if (onClickRow) {
      onClickRow(question);
    }
  };

  return (
    <TableContainer {...slotProps.tableContainer}>
      <Table>
        <TableHead>
          <TableRow headerRow>
            {columns.map(column => {
              const heading =
                typeof column.heading === 'function'
                  ? column.heading(dimensionsCount)
                  : column.heading;

              return (
                <TableCell
                  key={column.id}
                  sx={{ width: column.width }}
                >
                  <Title
                    title={heading}
                    variant="S"
                  />
                </TableCell>
              );
            })}
          </TableRow>
        </TableHead>
        <TableBody>
          {loading && (
            <SatisfactionTableContentSkeleton
              rows={5}
              hasDifferenceColumn={hasScoreDifference}
            />
          )}
          {!loading &&
            dimensions.map(dimension => (
              <TableRow
                key={dimension.id}
                onClick={handleRowClick(dimension)}
                hover
              >
                {columns.map(column => (
                  <TableCell
                    key={column.id}
                    sx={{ width: column.width }}
                  >
                    {column.renderCell(dimension)}
                  </TableCell>
                ))}
              </TableRow>
            ))}
          {loadingMore && (
            <SatisfactionTableContentSkeleton
              rows={3}
              hasDifferenceColumn={hasScoreDifference}
            />
          )}
        </TableBody>
      </Table>
    </TableContainer>
  );
};

export default SatisfactionDimensionsTable;
