import { useState } from 'react';
import { Helmet } from 'react-helmet-async';
import {
  FormProvider,
  useFieldArray,
  useForm,
  useWatch,
} from 'react-hook-form';
import { useMutation, useQuery } from 'react-query';
import { useNavigate, useParams } from 'react-router';

import { uniqueId } from 'lodash-es';
import { useModal } from '@material-hu/hooks/useModal';
import AddIcon from '@material-hu/icons/material/Add';
import CloseIcon from '@material-hu/icons/material/Close';
import StartIcon from '@material-hu/icons/material/Start';
import Box from '@material-hu/mui/Box';
import Card from '@material-hu/mui/Card';
import Chip from '@material-hu/mui/Chip';
import Container from '@material-hu/mui/Container';
import Divider from '@material-hu/mui/Divider';
import Grid from '@material-hu/mui/Grid';
import IconButton from '@material-hu/mui/IconButton';
import Stack from '@material-hu/mui/Stack';
import Tooltip from '@material-hu/mui/Tooltip';
import Typography from '@material-hu/mui/Typography';

import useSnackbarUtils from '@material-hu/components/deprecated/Snackbar';
import Button from '@material-hu/components/design-system/Buttons/Button';
import HuTooltip from '@material-hu/components/design-system/Tooltip';

import useFeatureFlag from 'src/hooks/useFeatureFlag';
import useNewTheme from 'src/hooks/useNewTheme';
import useUnsavedWarning from 'src/hooks/useUnsavedWarning';
import * as performanceService from 'src/services/performanceService';
import { FeatureFlags } from 'src/types/featureFlags';
import {
  type CreateReviewTemplate,
  ReviewCommentableStatus,
  type ReviewQuestion,
  ReviewQuestionOrigin,
  ReviewQuestionStatus,
  ReviewQuestionType,
  SpecialQuestionType,
} from 'src/types/performance';
import { formatTitle } from 'src/utils/helmetUtils';
import { useLokaliseTranslation } from 'src/utils/i18n';
import {
  validateMaxStringRule,
  validateRequiredStringRule,
} from 'src/utils/validation';

import CenteredCircularProgress from 'src/components/CircularProgress';
import FormRichEditor from 'src/components/FormInputs/FormRichEditor';
import FormSwitch from 'src/components/FormInputs/FormSwitch';
import FormTextField from 'src/components/FormInputs/FormTextField';
import ReviewQuestionLabelStatus from 'src/components/ReviewQuestionLabelStatus';

import { REVIEWS_BACKGROUND } from '../../../constants';
import { reviewsKeys } from '../../../queries';
import {
  getAnswerRequired,
  getCommentableStatus,
  getDefaultQuestion,
  getQuestionType,
  isQuestionDirty,
} from '../../../utils';
import {
  TEMPLATE_INSTRUCTIONS_MAX_LENGTH,
  TEMPLATE_TITLE_MAX_LENGTH,
} from '../../constants';
import {
  type PossibleAnswer,
  type QuestionTemplate,
  type TemplateFormValues,
} from '../../types';
import {
  buildCompetenciesQuestionTemplate,
  buildGoalsQuestionTemplate,
  defaultValuesTemplate,
} from '../../utils';

import IncludeCompetencies from './IncludeCompetencies';
import IncludeGoalType from './IncludeGoalType';
import QuestionsBank from './QuestionsBank';
import QuestionTemplates from './QuestionTemplates';
import TemplatePreview, {
  type TemplatePreviewProps,
} from './TemplatePreview/TemplatePreview';

const Template = () => {
  const [showBank, setShowBank] = useState(true);
  const [notIncludingIds, setNotIncludingIds] = useState<number[]>([]);
  const [activeQuestionId, setActiveQuestionId] = useState<number | null>(null);

  const { t } = useLokaliseTranslation(['performance', 'general']);
  const navigate = useNavigate();
  const { id } = useParams();
  const { showSnackbar } = useSnackbarUtils();

  const NewThemeProvider = useNewTheme();

  const defaultGoalQuestion = getDefaultQuestion(SpecialQuestionType.GOAL, t);
  const defaultCompetenciesQuestion = getDefaultQuestion(
    SpecialQuestionType.COMPETENCIES,
    t,
  );

  const newQuestion = {
    title: t('questions.no_name_question'),
    origin: ReviewQuestionOrigin.PERFORMANCE_REVIEW,
    status: ReviewQuestionStatus.DRAFT,
    type: ReviewQuestionType.TEXT,
    possibleAnswers: [
      { value: `${t('questions.ANSWER')} 1`, id: uniqueId('answer_') },
    ],
    commentableStatus: ReviewCommentableStatus.REQUIRED,
    answerRequired: true,
    commentRequired: false,
    hasComment: false,
    description: '',
    hasAnswer: false,
    new: true,
  };

  const { modal: previewModal, showModal: showPreviewModal } =
    useModal<TemplatePreviewProps>(TemplatePreview);

  const form = useForm<TemplateFormValues>({
    defaultValues: {
      title: t('templates.new_template'),
      hasInstructions: false,
      description: '',
      questionTemplates: [],
      status: ReviewQuestionStatus.DRAFT,
      includeGoals: false,
      includeCompetencies: false,
      goalType: null,
      goalQuestion: defaultGoalQuestion,
      competenciesQuestion: defaultCompetenciesQuestion,
    },
    mode: 'onChange',
  });

  const isCompetenciesFlagEnabled = useFeatureFlag(
    FeatureFlags.COMPETENCIES_ENABLED,
  );

  const {
    setValue,
    control,
    getValues,
    formState: { dirtyFields, isDirty },
  } = form;

  const { append, remove, insert, move } = useFieldArray({
    name: 'questionTemplates',
    control,
  });

  const questionTemplates = useWatch({ control, name: 'questionTemplates' });
  const includeGoals = useWatch({ control, name: 'includeGoals' });
  const includeCompetencies = useWatch({
    control,
    name: 'includeCompetencies',
  });
  const goalQuestion = useWatch({ control, name: 'goalQuestion' });
  const competenciesQuestion = useWatch({
    control,
    name: 'competenciesQuestion',
  });
  const title = useWatch({ control, name: 'title' });
  const hasInstructions = useWatch({ control, name: 'hasInstructions' });
  const status = useWatch({ control, name: 'status' });

  const templateId = id ? parseInt(id, 10) : null;
  const { isLoading: templatesLoading, refetch } = useQuery(
    reviewsKeys.template(templateId),
    () => performanceService.getReviewTemplate(templateId ?? 0),
    {
      select: r => r.data,
      enabled: !!templateId,
      onSuccess: data => {
        const formData = defaultValuesTemplate(
          data,
          t,
          defaultGoalQuestion,
          defaultCompetenciesQuestion,
        );

        form.reset(formData);

        setNotIncludingIds(
          data.formTemplate.questionTemplates.map((q: ReviewQuestion) => q.id),
        );
      },
    },
  );

  const getMutationErrorMessage = (error: unknown): string => {
    const data = (error as { response?: { data?: { message?: string } } })
      ?.response?.data;
    return data?.message || t('general:error');
  };

  const updateTemplateMutation = useMutation(
    (updatedTemplate: Partial<CreateReviewTemplate>) =>
      performanceService.updateTemplate(templateId ?? 0, updatedTemplate),
    {
      onSuccess: () => {
        showSnackbar(t('templates.template_updated'));
        navigate('/performance/templates');
        refetch();
      },
      onError: (error: unknown) => {
        showSnackbar(getMutationErrorMessage(error));
      },
    },
  );

  const createTemplateMutation = useMutation(
    (newTemplate: CreateReviewTemplate) =>
      performanceService.createTemplate(newTemplate),
    {
      onSuccess: () => {
        showSnackbar(t('templates.template_created'));
        navigate('/performance/templates');
      },
      onError: (error: unknown) => {
        showSnackbar(getMutationErrorMessage(error));
      },
    },
  );

  const { modal } = useUnsavedWarning(undefined, !isDirty);

  const getTooltipMessage =
    includeGoals && !goalQuestion?.hasAnswer && !goalQuestion?.hasComment
      ? t('templates.tooltip_goal_without_answer')
      : '';

  const canSaveTemplate =
    includeCompetencies || includeGoals || questionTemplates?.length > 0;

  const isEditingQuestion = activeQuestionId !== null;
  const currentQuestion = isEditingQuestion
    ? questionTemplates?.find(
        (q: QuestionTemplate) => q.id === activeQuestionId,
      )
    : null;

  const isCurrentQuestionInvalid =
    currentQuestion &&
    ((!currentQuestion.hasAnswer && !currentQuestion.hasComment) ||
      (currentQuestion.hasComment &&
        currentQuestion.commentRequired === undefined));

  const canCreateNewQuestion = !isEditingQuestion || !isCurrentQuestionInvalid;

  const hasInvalidQuestions = questionTemplates?.some(
    (question: QuestionTemplate) => !question.hasAnswer && !question.hasComment,
  );

  const handleClose = () => {
    if (activeQuestionId !== null) {
      setActiveQuestionId(null);
      return;
    }
    navigate('/performance/templates');
  };

  const addNewQuestion = () => {
    const newId = parseInt(uniqueId(), 10);

    append({
      ...newQuestion,
      id: newId,
    } as unknown as QuestionTemplate);

    setActiveQuestionId(newId);
  };

  const handleSave = () => {
    if (activeQuestionId !== null) {
      setActiveQuestionId(null);
      return;
    }

    const formValues = getValues();
    const hasQuestions = formValues.questionTemplates?.length > 0;

    const { goalsProgressMode, goalsQuestionTemplate } =
      buildGoalsQuestionTemplate(
        formValues.includeGoals,
        formValues.goalType,
        formValues.goalQuestion,
      );

    const competenciesQuestionTemplate = buildCompetenciesQuestionTemplate(
      formValues.includeCompetencies,
      formValues.competenciesQuestion,
    );

    const updatedTemplate: CreateReviewTemplate = {
      title: formValues.title,
      hasInstructions: formValues.hasInstructions,
      description: hasInstructions ? formValues.description : null,
      status: formValues.status,
      questionTemplates: hasQuestions
        ? (formValues.questionTemplates.map(
            (q: QuestionTemplate, idx: number) => {
              const questionType = getQuestionType(
                q.hasAnswer ?? false,
                q.type,
              );
              const commentableStatus = getCommentableStatus({
                hasComment: q.hasComment ?? false,
                commentRequired: q.commentRequired ?? false,
              });
              const answerRequired = getAnswerRequired(
                questionType,
                commentableStatus,
                q.answerRequired,
              );

              return {
                ...q,
                commentableStatus,
                answerRequired,
                possibleAnswers: q.possibleAnswers.map(
                  (a: PossibleAnswer) => a.value,
                ),
                id: q.new ? null : q.id,
                edited: isQuestionDirty(
                  dirtyFields as unknown as Partial<TemplateFormValues>,
                  idx,
                ),
              };
            },
          ) as ReviewQuestion[])
        : null,
      goalsQuestionTemplate,
      goalsProgressMode,
      competenciesQuestionTemplate,
    };

    const handleSuccess = () => {
      form.reset(formValues, { keepValues: true });
      setTimeout(() => {
        navigate('/performance/templates');
      }, 0);
    };

    if (templateId) {
      updateTemplateMutation.mutate(updatedTemplate, {
        onSuccess: () => {
          handleSuccess();
          refetch();
        },
      });
    } else {
      createTemplateMutation.mutate(updatedTemplate, {
        onSuccess: handleSuccess,
      });
    }
  };

  if (templatesLoading) return <CenteredCircularProgress centered />;

  const isTemplateInUse = status === ReviewQuestionStatus.IN_USE;

  return (
    <NewThemeProvider>
      {previewModal}
      {modal}
      <Stack
        direction="column"
        sx={{ height: '100%' }}
      >
        <Helmet>
          <title>
            {formatTitle(
              t(`templates.${templateId ? 'EDIT' : 'NEW'}_TEMPLATE`),
            )}
          </title>
        </Helmet>

        <Box
          sx={{
            backgroundColor: 'background.default',
            flex: 1,
            pt: 1,
          }}
        >
          <Container
            maxWidth={false}
            disableGutters
          >
            <FormProvider {...form}>
              <Box
                sx={{
                  top: -5,
                  left: 0,
                  zIndex: 200,
                  px: 2,
                  position: 'sticky',
                  backgroundColor: 'background.default',
                }}
              >
                <Grid
                  container
                  spacing={3}
                  mb={2}
                >
                  <Grid
                    item
                    xs
                  >
                    <Stack
                      direction="row"
                      alignItems="center"
                    >
                      <IconButton
                        sx={{ mr: 2 }}
                        onClick={handleClose}
                      >
                        <CloseIcon />
                      </IconButton>
                      <Typography
                        variant="h5"
                        color="textPrimary"
                        sx={{ display: 'inline', mr: 2, maxLines: 1 }}
                        style={{
                          maxWidth: 600,
                          overflow: 'hidden',
                          textOverflow: 'ellipsis',
                          whiteSpace: 'nowrap',
                        }}
                      >
                        {title}
                      </Typography>
                      <ReviewQuestionLabelStatus status={status} />
                    </Stack>
                  </Grid>
                  <Grid item>
                    <IconButton
                      sx={{
                        position: 'absolute',
                        display: 'flex',
                        top: 110,
                        borderRadius: 0,
                        width: '5%',
                        backgroundColor: !showBank
                          ? REVIEWS_BACKGROUND
                          : 'white',
                        '&:hover': {
                          backgroundColor: !showBank
                            ? `${REVIEWS_BACKGROUND} !important`
                            : 'white !important',
                        },
                        right: !showBank ? '1.5%' : '26.5%',
                        justifyContent: !showBank ? 'left' : 'right',
                      }}
                      onClick={() => setShowBank(!showBank)}
                    >
                      <StartIcon
                        fontSize="medium"
                        color="secondary"
                        sx={{
                          transform: !showBank ? 'rotate(180deg)' : 'none',
                        }}
                      />
                    </IconButton>
                    <Button
                      variant="outlined"
                      sx={{ mr: 2, py: 1 }}
                      onClick={() =>
                        showPreviewModal({
                          watch: () => getValues(),
                        })
                      }
                    >
                      {t('general:preview')}
                    </Button>
                    <Tooltip title={getTooltipMessage}>
                      <span>
                        <Button
                          disabled={
                            !isDirty ||
                            !canSaveTemplate ||
                            hasInvalidQuestions ||
                            (includeGoals &&
                              !goalQuestion?.hasAnswer &&
                              !goalQuestion?.hasComment) ||
                            (includeCompetencies &&
                              !competenciesQuestion?.hasAnswer &&
                              !competenciesQuestion?.hasComment)
                          }
                          onClick={handleSave}
                          variant="contained"
                          sx={{ py: 1, mr: 2 }}
                        >
                          {t(
                            `templates.${templateId ? 'UPDATE' : 'CREATE'}_TEMPLATE`,
                          )}
                        </Button>
                      </span>
                    </Tooltip>
                  </Grid>
                </Grid>
                <Divider />
              </Box>
              <Stack direction="row">
                <Stack sx={{ width: showBank ? '70%' : '99%' }}>
                  <Box sx={{ mt: 5, mx: 'auto', width: 600 }}>
                    <FormTextField
                      label={t('templates.template_name')}
                      margin="normal"
                      name="title"
                      fullWidth
                      showCounter
                      maxLength={TEMPLATE_TITLE_MAX_LENGTH}
                      inputProps={{ maxLength: TEMPLATE_TITLE_MAX_LENGTH }}
                      rules={{
                        validate: {
                          required: validateRequiredStringRule,
                          maxLength: validateMaxStringRule(
                            TEMPLATE_TITLE_MAX_LENGTH,
                          ),
                        },
                      }}
                    />
                    <Stack
                      alignItems="center"
                      direction="row"
                    >
                      <Button
                        onClick={() =>
                          setValue('hasInstructions', !hasInstructions, {
                            shouldDirty: true,
                          })
                        }
                        variant="text"
                        sx={{ mt: 2, mb: 1 }}
                        startIcon={
                          hasInstructions ? (
                            <CloseIcon
                              fontSize="small"
                              sx={{ color: 'black', mr: 1 }}
                            />
                          ) : (
                            <AddIcon
                              fontSize="small"
                              sx={{ color: 'black', mr: 1 }}
                            />
                          )
                        }
                      >
                        <Typography
                          variant="subtitle2"
                          color="black"
                        >
                          {t(
                            hasInstructions
                              ? 'templates.remove_instructions'
                              : 'templates.add_instructions',
                          )}
                        </Typography>
                      </Button>
                    </Stack>
                    {hasInstructions && (
                      <FormRichEditor
                        toolbar="bold italic underline strikethrough | bullist numlist | link"
                        name="description"
                        simplifyEditor
                        placeholder={t('templates.instructions_placeholder')}
                        maxLength={TEMPLATE_INSTRUCTIONS_MAX_LENGTH}
                        showCounter
                      />
                    )}
                    <Stack
                      direction="row"
                      alignItems="center"
                      mt={3}
                      mb={3}
                    >
                      <Typography variant="h5">
                        {t('questions.title')}
                      </Typography>
                      <Chip
                        label={questionTemplates?.length || 0}
                        color="primary"
                        size="small"
                        sx={{ p: 0, ml: 1, fontSize: '11px' }}
                      />
                    </Stack>
                    {!templatesLoading && (
                      <QuestionTemplates
                        move={move}
                        remove={remove}
                        insert={insert}
                        notIncludingIds={notIncludingIds}
                        questionTemplates={questionTemplates}
                        setNotIncludingIds={setNotIncludingIds}
                        activeQuestionId={activeQuestionId}
                        setActiveQuestionId={setActiveQuestionId}
                        isTemplateInUse={isTemplateInUse}
                      />
                    )}
                    <Button
                      variant="contained"
                      fullWidth
                      sx={{ mt: 2 }}
                      onClick={() => addNewQuestion()}
                      disabled={!canCreateNewQuestion}
                    >
                      {t('questions.new_question')}
                    </Button>
                    <Card sx={{ my: 4, p: 4 }}>
                      <Stack
                        sx={{
                          flexDirection: 'row',
                          justifyContent: 'space-between',
                          alignItems: 'center',
                          mb: 1,
                        }}
                      >
                        <Typography variant="h6">
                          {t('templates.include_goals')}
                        </Typography>
                        <HuTooltip
                          title={
                            isTemplateInUse
                              ? t(
                                  'templates.include_goals_and_competencies_disabled',
                                )
                              : ''
                          }
                          disableTooltip={!isTemplateInUse}
                        >
                          <Stack
                            direction="row"
                            alignItems="center"
                          >
                            <FormSwitch
                              name="includeGoals"
                              disabled={isTemplateInUse}
                            />
                          </Stack>
                        </HuTooltip>
                      </Stack>

                      <Typography variant="body1">
                        {t('templates.include_goals_description')}
                      </Typography>

                      {includeGoals && <IncludeGoalType />}
                    </Card>
                    {isCompetenciesFlagEnabled && (
                      <Card sx={{ my: 4, p: 4 }}>
                        <Stack
                          sx={{
                            flexDirection: 'row',
                            justifyContent: 'space-between',
                            alignItems: 'center',
                            mb: 1,
                          }}
                        >
                          <Typography variant="h6">
                            {t('templates.include_competencies')}
                          </Typography>
                          <HuTooltip
                            title={
                              isTemplateInUse
                                ? t(
                                    'templates.include_goals_and_competencies_disabled',
                                  )
                                : ''
                            }
                            disableTooltip={!isTemplateInUse}
                          >
                            <Stack
                              direction="row"
                              alignItems="center"
                            >
                              <FormSwitch
                                name="includeCompetencies"
                                disabled={isTemplateInUse}
                              />
                            </Stack>
                          </HuTooltip>
                        </Stack>
                        <Typography variant="body1">
                          {t('templates.include_competencies_description')}
                        </Typography>

                        {includeCompetencies && <IncludeCompetencies />}
                      </Card>
                    )}
                  </Box>
                </Stack>
                <Stack
                  sx={{
                    width: showBank ? '30%' : '1%',
                    backgroundColor: REVIEWS_BACKGROUND,
                    minHeight: '100%',
                    px: 2,
                    pt: 12,
                  }}
                  spacing={2}
                >
                  {showBank && (
                    <QuestionsBank
                      append={append}
                      notIncludingIds={notIncludingIds}
                      setNotIncludingIds={setNotIncludingIds}
                    />
                  )}
                </Stack>
              </Stack>
            </FormProvider>
          </Container>
        </Box>
      </Stack>
    </NewThemeProvider>
  );
};

export default Template;
