import React, {useCallback, useMemo} from 'react';
import {View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {useController} from 'react-hook-form';
import {
  Typography,
  Image,
  FileCard,
  InputClassicController,
  InputDateController,
  InputDropdownController,
  InputMoneyController,
  InputPhoneController,
  InputTimeController,
  InputYearMonthPickerController,
  RatingController,
  TableController,
  FlagKey,
} from '@components';
import {UploaderInputs} from '@components/_HuGo/Uploader';
import {Attachment, FileAsset} from '@interfaces/attachments';
import {InputType, MediaQuestion, Question} from '@interfaces/questions';
import {SURVEYS_MAX_ATTACHMENTS} from '@modules/surveys/constants';
import {useTheme} from '@shared/theme';
import {sizeToBytes} from '@shared/utils';
import {InputSelectableListController} from '@shared/dynamicForms/components/FormInput/components/InputSelectableList';
import {FormUploader} from '@shared/dynamicForms/components/FormInput/components/FormUploader';
import {DigitalSignatureController} from '@shared/dynamicForms/components/FormInput/components/DigitalSignatureController';

import {styles} from './styles';

const MINUTE_INTERVAL = 1;
const MAX_NUMERIC_LENGTH = 21;
export const HIDE_REQUIRED_LABEL_INPUT_TYPES = [
  InputType.INFO,
  InputType.AUTOCOMPLETE,
];

interface Props {
  question: Question;
  isCompleted?: boolean;
  stepHasRequired?: boolean;
}

function FormInput({
  question,
  isCompleted = false,
  stepHasRequired = true,
}: Props) {
  const {t} = useTranslation();
  const {theme} = useTheme();
  const name = question.id.toString();
  const {fieldState, field} = useController({name});
  const hideRequiredLabel =
    HIDE_REQUIRED_LABEL_INPUT_TYPES.includes(question.inputType) ||
    !stepHasRequired;
  const isError = !!fieldState.error?.message;
  const textColor = isError
    ? theme.text.feedback.error
    : theme.text.neutral.default;

  const options = useMemo(() => {
    if (
      question.inputType === InputType.DROPDOWN ||
      question.inputType === InputType.CHECKBOX
    ) {
      return question.options.map(option => ({
        id: option.id,
        label: option.description,
      }));
    }

    return [];
  }, [question]);

  const isDatePicker = question.inputType === InputType.DATE;
  const isFloat = question.inputType === InputType.DECIMAL;

  const disabled = question.disabled || isCompleted;

  const rows = useMemo(() => {
    return question.rows?.map(row => ({
      id: row.id,
      label: row.description,
    }));
  }, [question.rows]);

  const columns = useMemo(() => {
    return question.options?.map(option => ({
      id: option.id,
      label: option.description,
    }));
  }, [question.options]);

  const renderInput = useCallback(() => {
    switch (question.inputType) {
      case InputType.INFO:
        return null;
      case InputType.TEXT:
        return (
          <InputClassicController
            name={name}
            placeholder={t('service_management.input_placeholder.text')}
            autoCorrect={false}
            autoComplete="off"
            disabled={disabled}
          />
        );
      case InputType.RATE:
        return (
          <RatingController name={name} showErrorHelper disabled={disabled} />
        );
      case InputType.DECIMAL:
      case InputType.INTEGER:
        return (
          <InputMoneyController
            name={name}
            withDecimals={isFloat}
            placeholder={t(
              isFloat
                ? 'service_management.input_placeholder.float'
                : 'service_management.input_placeholder.integer',
            )}
            currencySymbol=""
            withLimitDecimals={isFloat}
            maxLength={MAX_NUMERIC_LENGTH}
            disabled={disabled}
          />
        );
      case InputType.DROPDOWN:
        return (
          <InputDropdownController
            name={name}
            options={options}
            disabled={disabled}
            placeholder={t('service_management.input_placeholder.dropdown')}
            searchPlaceholder={t('general.search')}
            multipleSelect={question.multipleAnswer}
            filterable
          />
        );
      case InputType.CHECKBOX:
        return (
          <InputSelectableListController
            name={name}
            options={options}
            multipleSelect={question.multipleAnswer}
            disabled={disabled}
            defaultValue={question.multipleAnswer ? [] : undefined}
          />
        );
      case InputType.DATE:
      case InputType.DATE_MMAAAA:
        return isDatePicker ? (
          <InputDateController
            name={name}
            disabled={disabled}
            placeholder={t('service_management.enter_date')}
          />
        ) : (
          <InputYearMonthPickerController
            name={name}
            disabled={disabled}
            placeholder={t('service_management.enter_month_year')}
          />
        );
      case InputType.TIME:
        return (
          <InputTimeController
            name={name}
            disabled={disabled}
            placeholder="00:00"
            minuteInterval={MINUTE_INTERVAL}
          />
        );
      case InputType.PHONE:
        return (
          <InputPhoneController
            name={name}
            disabled={disabled}
            defaultCountryCode={
              question.properties?.defaultCountryCode as FlagKey
            }
          />
        );
      case InputType.CHECKBOX_GRID:
        return (
          <TableController
            name={name}
            rows={rows}
            columns={columns}
            multiple={!!question.multipleAnswer}
            disabled={disabled}
          />
        );
      case InputType.AUTOCOMPLETE:
        return <InputClassicController name={name} editable={false} disabled />;
      case InputType.MEDIA:
      case InputType.FILE:
        if (isCompleted) {
          return question.answer?.attachments?.map((file: Attachment) => (
            <FileCard
              id={file.id?.toString() || ''}
              name={file.name || ''}
              path={file.url || ''}
              url={file.url || ''}
              size={sizeToBytes(file.size || '')}
              downloadWithAuthHeader
            />
          ));
        }
        return (
          <FormUploader
            name={name}
            disabled={disabled}
            initialFiles={field.value as FileAsset[] | undefined}
            inputs={
              question.inputType === InputType.FILE
                ? [UploaderInputs.Documents]
                : [
                    UploaderInputs.Video,
                    UploaderInputs.Gallery,
                    UploaderInputs.Camera,
                  ]
            }
            maxAttachments={SURVEYS_MAX_ATTACHMENTS}
          />
        );
      case InputType.DIGITAL_SIGN:
        if (isCompleted) {
          return (
            <Image
              style={[
                styles.signature,
                {backgroundColor: theme.action.background.brand.disabled},
              ]}
              source={{
                uri: (question as unknown as MediaQuestion).answer
                  ?.attachments?.[0]?.url,
              }}
              contentFit="contain"
            />
          );
        }
        return (
          <DigitalSignatureController
            name={name}
            title={''}
            disabled={disabled}
            persistedSignature
          />
        );
      default:
        return null;
    }
  }, [
    columns,
    disabled,
    field.value,
    isCompleted,
    isDatePicker,
    isFloat,
    name,
    options,
    question,
    rows,
    t,
    theme.action.background.brand.disabled,
  ]);

  return (
    <View
      style={[
        styles.commonContainer,
        {backgroundColor: theme.background.layout.tertiary},
      ]}>
      <Typography weight="semiBold" color={textColor}>
        {question.description}
        {!hideRequiredLabel && (
          <Typography weight="semiBold" color={textColor}>
            {question.required
              ? ' *'
              : ` (${t('general.optional').toLowerCase()})`}
          </Typography>
        )}
      </Typography>
      {!!question.attachments?.length && (
        <View style={styles.attachments}>
          {question.attachments?.map(attachment => (
            <FileCard
              id={attachment.id.toString()}
              name={attachment.name}
              path={attachment.url}
              url={attachment.url}
              size={sizeToBytes(attachment.size || '')}
              downloadWithAuthHeader
              showCheckIcon={false}
              showFileTypeIcon
            />
          ))}
        </View>
      )}
      {renderInput()}
    </View>
  );
}

export default FormInput;
