import React, {ReactNode, memo, useCallback, useMemo} from 'react';
import {View} from 'react-native';
import {Divider, Typography, HtmlRender, Title, Tooltip} from '@components';
import {
  CompetencyMetadata,
  FormCommentableType,
  FormInputType,
  FormStep,
  FormValue,
} from '@components/DynamicForm/interfaces';
import FormTextInput from '@components/DynamicForm/components/inputs/FormTextInput';
import FormCheckbox from '@components/DynamicForm/components/inputs/FormCheckbox';
import FormMultipleChoice from '@components/DynamicForm/components/inputs/FormMultipleChoice';
import FormRating from '@components/DynamicForm/components/inputs/FormRating';
import FormComment from '@components/DynamicForm/components/inputs/FormComment';
import FormDescription from '@components/DynamicForm/components/inputs/FormDescription';
import {useDraftForm} from '@modules/performance/hooks/useDraftForm';
import {useTheme} from '@shared/theme';

import {styles} from './styles';

interface Props {
  reviewId: number;
  data: FormStep;
  HeaderComponent?: ReactNode;
  BodyComponent?: (data: FormStep) => ReactNode;
  disabled?: boolean;
}

function FormItem({
  reviewId,
  data,
  HeaderComponent = null,
  BodyComponent,
  disabled,
}: Props) {
  const {theme} = useTheme();
  const {label, description, input, name, rules, answer, commentable, comment} =
    data;

  const {draftForm, updateDraftForm} = useDraftForm(reviewId);

  const onChange = useCallback(
    (value: FormValue) => {
      updateDraftForm({
        ...draftForm,
        [name]: {value, comment: draftForm?.[name]?.comment},
      });
    },
    [name, updateDraftForm, draftForm],
  );

  const onCommentChange = useCallback(
    (value: string) => {
      updateDraftForm({
        ...draftForm,
        [name]: {value: draftForm?.[name]?.value, comment: value},
      });
    },
    [name, updateDraftForm, draftForm],
  );

  const isCommentable = useMemo(
    () =>
      commentable &&
      commentable !== FormCommentableType.NONE &&
      input.type !== FormInputType.TEXT,
    [commentable, input.type],
  );

  const renderInput = useCallback(() => {
    switch (input.type) {
      case FormInputType.CHECKBOX:
        return (
          <FormCheckbox
            name={name}
            options={input.options}
            disabled={disabled}
            initialValue={answer as number}
            onChangeInput={onChange}
          />
        );
      case FormInputType.MULTIPLE_CHOICE:
        return (
          <FormMultipleChoice
            name={name}
            options={input.options}
            disabled={disabled}
            initialValue={answer as number[]}
            onChangeInput={onChange}
          />
        );
      case FormInputType.RATING:
        return (
          <FormRating
            name={name}
            options={input.options}
            disabled={disabled}
            initialValue={answer as number}
            onChangeInput={onChange}
          />
        );
      case FormInputType.DESCRIPTION:
        return (
          <FormDescription
            description={input.description}
            isHtml={input.isHtml}
          />
        );
      case FormInputType.TEXT:
      default:
        return (
          <FormTextInput
            disabled={disabled}
            initialValue={answer as string}
            name={name}
            onChangeInput={onChange}
          />
        );
    }
  }, [input, disabled, answer, name, onChange]);

  const category = (data.metadata as CompetencyMetadata)?.category;

  return (
    <>
      {input.type !== FormInputType.DESCRIPTION && HeaderComponent}
      {!!category && (
        <>
          <View style={styles.categoryContainer}>
            <Title title={category.name} />
            <Tooltip info={category.description} title={category.name} />
          </View>
          <View style={styles.dividerContainer}>
            <Divider />
          </View>
        </>
      )}
      {!!label && !!input.type && (
        <Typography
          variant="m"
          style={!!HeaderComponent && styles.label}
          weight="semiBold">
          {`${label} ${rules?.required ? '*' : ''}`}
        </Typography>
      )}
      {description && (
        <View>
          {description.isHTML ? (
            <HtmlRender
              html={description.value}
              textStyle={[
                styles.htmlDescription,
                {color: theme.text.neutral.lighter},
              ]}
            />
          ) : (
            <Typography color={theme.text.neutral.lighter}>
              {description.value}
            </Typography>
          )}
        </View>
      )}
      <View
        style={[
          styles.optionsContainer,
          ...(!input.type ? [styles.marginBottom] : []),
          ...((data.metadata as {type: 'goal' | 'competency'})?.type ===
          'competency'
            ? [
                styles.competencyContainer,
                {
                  backgroundColor: theme.background.elements.grey,
                },
              ]
            : []),
        ]}>
        {!!BodyComponent && BodyComponent(data)}
        {!!input.type && renderInput()}
        {isCommentable && (
          <>
            <Divider />
            <FormComment
              type={commentable!}
              name={name}
              disabled={disabled}
              initialValue={comment}
              onCommentChange={onCommentChange}
            />
          </>
        )}
      </View>
    </>
  );
}

export default memo(FormItem);
