import { memo, type ReactNode } from 'react';
import { Controller, useFormContext } from 'react-hook-form';

import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import TextArea from '@material-hu/components/design-system/Inputs/TextArea';
import HuTitle from '@material-hu/components/design-system/Title';

import { type Goal } from 'src/pages/dashboard/goals/types';
import {
  COMMENT,
  type ReviewCommentableStatus,
  ReviewQuestionType,
} from 'src/pages/dashboard/performance/types';
import { type Competency } from 'src/types/competencies';
import { useLokaliseTranslation } from 'src/utils/i18n';

import FormRichEditor from 'src/components/dashboard/form/formDetail/inputs/FormRichEditor';
import ScoreInput from 'src/components/dashboard/form/formDetail/inputs/ScoreInput';

import { isCommentRequired, needsAComment } from '../utils';

import ProgressBar from './Goal/ProgressBar';
import ReviewPerformanceMultipleChoiceCards from './Inputs/ReviewPerformanceMultipleChoiceCards';
import ReviewPerformanceSingleChoiceCards from './Inputs/ReviewPerformanceSingleChoiceCards';
import RichText from './RichText';

export type ReviewInput = {
  index: number;
  id?: string;
  title: string;
  type?: ReviewQuestionType;
  description?: string;
  choices?: string[];
  required?: boolean;
  answer?: string | number | number[] | undefined;
  answered: boolean;
  commentableStatus: ReviewCommentableStatus;
  comment?: string;
  goal?: Goal;
  competency?: Competency;
  canViewGoalDetails: boolean;
  headerActions?: ReactNode;
};

const reviewQuestionCardSx = {
  p: 3,
  borderRadius: '20px',
  backgroundColor: 'background.paper',
  borderColor: 'divider',
  borderWidth: 1,
  borderStyle: 'solid',
  width: '100%',
  boxSizing: 'border-box' as const,
};

/** API/CMS often append " *" to the question copy; we show a red marker via Typography instead. */
const stripTrailingRequiredAsterisks = (value: string) =>
  value.replace(/\s*\*+\s*$/u, '').trim();

const ReviewCommentEditor = ({
  id,
  comment,
  commentRequired,
  showCommentBox,
  t,
}: {
  id?: string;
  comment?: string;
  commentRequired: boolean;
  showCommentBox: boolean;
  t: (key: string) => string;
}) => {
  const { control } = useFormContext();
  const name = `${id}${COMMENT}`;

  if (!showCommentBox) {
    return null;
  }

  return (
    <Controller
      control={control}
      name={name}
      defaultValue={comment ?? ''}
      rules={{ required: commentRequired }}
      render={({ field, fieldState }) => (
        <TextArea
          content={field.value ?? ''}
          onChange={field.onChange}
          onBlur={field.onBlur}
          label={`${t('review_input.leave_comment')}${commentRequired ? ' *' : ''}`}
          simplifyEditor
          error={!!fieldState.error}
          errorText={fieldState.error?.message}
          sx={{
            '& .text-area-actions-bar > .MuiStack-root': {
              backgroundColor: theme =>
                theme.palette.new.background.elements.grey,
            },
          }}
        />
      )}
    />
  );
};

const getInput = {
  [ReviewQuestionType.TEXT]: (props: ReviewInput) => {
    const { id, required, answered, answer } = props;
    const { t } = useLokaliseTranslation('performance');

    if (answered) return <RichText text={answer as string} />;

    return (
      <FormRichEditor
        rules={{ required }}
        placeholder={t('summary.placeholder')}
        name={id || ''}
        defaultValue={answer}
      />
    );
  },
  [ReviewQuestionType.CHECKBOX]: (props: ReviewInput) => {
    const {
      id,
      choices,
      commentableStatus,
      required,
      answered,
      answer,
      comment,
    } = props;
    const { t } = useLokaliseTranslation('performance');

    const showCommentBox = needsAComment(commentableStatus) && !answered;
    const showAnswerComment = answered && comment;
    const commentRequired = isCommentRequired(commentableStatus);
    const choiceLabels = choices || [];

    return (
      <>
        {!answered && (
          <Typography variant="body1">
            {t('review_input.select_all_options')}
          </Typography>
        )}
        <ReviewPerformanceMultipleChoiceCards
          name={id || ''}
          choiceLabels={choiceLabels}
          required={!!required}
          disabled={answered}
          defaultValue={(answer as number[] | undefined) ?? []}
        />
        <ReviewCommentEditor
          id={id}
          comment={comment}
          commentRequired={commentRequired}
          showCommentBox={showCommentBox}
          t={t}
        />
        {showAnswerComment && <RichText text={comment} />}
      </>
    );
  },
  [ReviewQuestionType.MULTIPLE_CHOICE]: (props: ReviewInput) => {
    const {
      id,
      choices,
      required,
      commentableStatus,
      answered,
      answer,
      comment,
    } = props;
    const { t } = useLokaliseTranslation('performance');

    const showCommentBox = needsAComment(commentableStatus) && !answered;
    const showAnswerComment = answered && comment;
    const commentRequired = isCommentRequired(commentableStatus);
    const choiceLabels = choices || [];

    return (
      <>
        {!answered && (
          <Typography variant="body1">
            {t('review_input.select_option')}
          </Typography>
        )}
        <ReviewPerformanceSingleChoiceCards
          name={id || ''}
          choices={choiceLabels}
          required={!!required}
          disabled={answered}
          defaultValue={answer as number | undefined}
        />
        <ReviewCommentEditor
          id={id}
          comment={comment}
          commentRequired={commentRequired}
          showCommentBox={showCommentBox}
          t={t}
        />
        {showAnswerComment && <RichText text={comment} />}
      </>
    );
  },
  [ReviewQuestionType.RATING]: (props: ReviewInput) => {
    const {
      id,
      choices,
      commentableStatus,
      required,
      answered,
      answer,
      comment,
    } = props;
    const { t } = useLokaliseTranslation('performance');

    const showCommentBox = needsAComment(commentableStatus) && !answered;
    const showAnswerComment = answered && comment;
    const commentRequired = isCommentRequired(commentableStatus);

    return (
      <>
        <ScoreInput
          answer={answer as number}
          formFilled={answered}
          name={id || ''}
          isRequired={required || false}
          options={choices || []}
          label={t('review_input.select_answer')}
        />
        <ReviewCommentEditor
          id={id}
          comment={comment}
          commentRequired={commentRequired}
          showCommentBox={showCommentBox}
          t={t}
        />
        {showAnswerComment && <RichText text={comment} />}
      </>
    );
  },
};

export const GetReviewInputComponent = (props: ReviewInput) => {
  const {
    id,
    title,
    description,
    index,
    required,
    type,
    goal,
    competency,
    canViewGoalDetails,
    headerActions,
  } = props;

  if (!(type && getInput[type])) {
    return null;
  }

  const hasGoals = !!goal;
  const hasCompetencies = !!competency;
  const titleDisplay = stripTrailingRequiredAsterisks(title);
  const titleText = hasCompetencies
    ? competency.name
    : `${index + 1}. ${titleDisplay}`;
  const titleWithRequiredMark = required ? `${titleText} *` : titleText;
  const descriptionToRender =
    (hasCompetencies ? competency.description : description) ?? description;
  const titleDescription = hasCompetencies
    ? descriptionToRender || undefined
    : undefined;

  return (
    <Stack
      key={id}
      sx={{
        ...reviewQuestionCardSx,
        flexDirection: 'column',
        gap: 2,
      }}
    >
      <Stack
        sx={{
          flexDirection: 'row',
          alignItems: 'flex-start',
          justifyContent: 'space-between',
          gap: 2,
          minWidth: 0,
        }}
      >
        <HuTitle
          variant="S"
          title={titleWithRequiredMark}
          description={titleDescription}
          sx={{
            flex: '0 1 auto',
            minWidth: 0,
            maxWidth: '100%',
            width: 'fit-content',
            '& > .MuiStack-root': {
              width: 'auto',
              maxWidth: '100%',
            },
          }}
        />
        {headerActions && (
          <Stack
            sx={{
              flexDirection: 'row',
              alignItems: 'center',
              gap: 1,
              flexShrink: 0,
            }}
          >
            {headerActions}
          </Stack>
        )}
      </Stack>
      {!hasCompetencies && !!descriptionToRender && (
        <RichText
          text={descriptionToRender}
          sx={{ color: 'text.secondary' }}
        />
      )}

      <Stack sx={{ flexDirection: 'column', gap: 2 }}>
        {hasGoals && (
          <ProgressBar
            goal={goal}
            canViewGoalDetails={canViewGoalDetails}
          />
        )}
        {getInput[type](props)}
      </Stack>
    </Stack>
  );
};

export default memo(GetReviewInputComponent);
