import { useMemo } from 'react';

import Pill from '@design-system/Pills';
import ProgressBar from '@design-system/ProgressIndicators/ProgressBar';
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 { compact } from 'lodash';

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

import {
  type QuestionDatum,
  type SatisfactionQuestionsTableProps,
  type TableColumn,
} from './types';

const SatisfactionQuestionsTable = <
  TQuestion extends QuestionDatum = QuestionDatum,
>({
  questions,
  questionsCount,
  questionsHeading,
  distributionHeading,
  scoreHeading,
  scoreDifferenceHeading,
  noAnswerLabel,
  openCommentLabel,
  tooltipLabels,
  getTooltipTitle,
  noScoreMessage,
  onRowClick,
  slotProps = {},
  loading = false,
  loadingMore = false,
  differenceIndicatorMeta,
}: SatisfactionQuestionsTableProps<TQuestion>) => {
  const theme = useTheme();

  const hasScoreDifference = useMemo(
    () =>
      questions.some(
        question =>
          question.type === 'LIKERT' && question.scoreDifference !== null,
      ),
    [questions],
  );

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

    return (
      <Tooltip description={noScoreMessage}>
        <IconInfoCircle
          size={20}
          color={theme.palette.new.text.neutral.default}
        />
      </Tooltip>
    );
  };

  const columns = useMemo(() => {
    const baseColumns: TableColumn[] = [
      {
        id: 'statement',
        heading: (count: number) =>
          `${questionsHeading} ${count ? `(${count})` : ''}`,
        width: '50%',
        renderCell: (row: QuestionDatum) => (
          <Title
            title={row.statement}
            description={compact([
              row.answersLabel,
              row.commentsLabel,
              row.topicLabel,
            ]).join(' | ')}
            variant="S"
            fontWeight="fontWeightRegular"
          />
        ),
      },
      {
        id: 'score',
        heading: scoreHeading,
        renderCell: renderScoreCell,
      },
    ];

    if (hasScoreDifference) {
      baseColumns.push({
        id: 'scoreDifference',
        heading: scoreDifferenceHeading,
        renderCell: (row: QuestionDatum) => {
          if (
            row.type === 'LIKERT' &&
            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: '40%',
        renderCell: (row: QuestionDatum) => {
          if (!row.hasThresholdPassed) {
            return (
              <Pill
                label={noAnswerLabel}
                type="disabled"
                size="medium"
                hasIcon={false}
              />
            );
          }

          switch (row.type) {
            case 'LIKERT':
              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}`
                  }
                />
              );
            case 'TEXT':
              return (
                <Pill
                  label={openCommentLabel}
                  type="neutral"
                  size="medium"
                  hasIcon={false}
                />
              );
            case 'SELECT':
              return (
                <ProgressBar
                  helper={`${row.scorePercentage}%: "${row.answer}"`}
                  current={row.scorePercentage}
                  total={100}
                  variant="determinate"
                />
              );
            default:
              return null;
          }
        },
      },
      {
        id: 'actions',
        heading: '',
        width: 24,
        renderCell: () => <IconChevronRight size={16} />,
      },
    );

    return baseColumns;
  }, [
    questionsHeading,
    scoreHeading,
    scoreDifferenceHeading,
    hasScoreDifference,
    distributionHeading,
    noAnswerLabel,
    openCommentLabel,
    tooltipLabels,
    getTooltipTitle,
    noScoreMessage,
    onRowClick,
    theme,
  ]);

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

  return (
    <TableContainer {...slotProps.tableContainer}>
      <Table>
        <TableHead>
          <TableRow headerRow>
            {columns.map(column => {
              const heading =
                typeof column.heading === 'function'
                  ? column.heading(questionsCount)
                  : 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 &&
            questions.map(question => (
              <TableRow
                key={question.id}
                onClick={handleRowClick(question)}
                hover
              >
                {columns.map(column => (
                  <TableCell
                    key={column.id}
                    sx={{ width: column.width }}
                  >
                    {column.renderCell(question)}
                  </TableCell>
                ))}
              </TableRow>
            ))}
          {loadingMore && (
            <SatisfactionTableContentSkeleton
              rows={3}
              hasDifferenceColumn={hasScoreDifference}
            />
          )}
        </TableBody>
      </Table>
    </TableContainer>
  );
};

export default SatisfactionQuestionsTable;
