import { useMemo } from 'react';
import { Controller, useFormContext } from 'react-hook-form';

import { type CountryCode, getCountryCallingCode } from 'libphonenumber-js';
import Stack from '@material-hu/mui/Stack';

import InputSelectableList from '@material-hu/components/composed-components/dynamic-forms/components/FormInputs/InputSelectableList';
import FormTimePicker from '@material-hu/components/composed-components/TimePicker/form';
import CardContainer from '@material-hu/components/design-system/CardContainer';
import FormAutocomplete from '@material-hu/components/design-system/Inputs/Autocomplete/form';
import FormInputClassic from '@material-hu/components/design-system/Inputs/Classic/form';
import FormDatePicker from '@material-hu/components/design-system/Inputs/DatePicker/form';
import FormInputPhone from '@material-hu/components/design-system/Inputs/Phone/form';
import FormRating from '@material-hu/components/design-system/Rating/form';

import { useAuth } from 'src/contexts/JWTContext';
import useRules from 'src/hooks/useRules';
import { useFormFileUpload } from 'src/pages/dashboard/forms/FormFileUploadContext';
import { transformIntegerInput } from 'src/pages/dashboard/serviceManagement/form/inputs/FloatInput';
import { InputType, type Question } from 'src/types/forms';
import {
  buildOptionsToDropDownCatalog,
  getDecimalSeparator,
  getThousandSeparator,
} from 'src/utils/form';
import { useLokaliseTranslation } from 'src/utils/i18n';

import QuestionAttachments from '../QuestionAttachments';

import AutocompleteInput from './AutocompleteInput';
import DigitalSignUploader from './DigitalSignUploader';
import FieldErrorMessage from './FieldErrorMessage';
import FileUploader from './FileUploader';
import FormRadioGrid from './FormRadioGrid';
import MediaUploader from './MediaUploader';
import QuestionTitle from './QuestionTitle';

const TEXT_MAX_LENGTH = 2048;
const TEXT_AREA_MAX_LENGTH = 8192;
const MAX_INTEGER_LENGTH = 15;
const DEFAULT_COUNTRY_CODE: CountryCode = 'AR';

type Props = {
  name: string;
  question: Question;
  formFilled: boolean;
};

const InputFieldWrapper = ({ name, question, formFilled }: Props) => {
  const { t } = useLokaliseTranslation(['forms', 'validations']);
  const { control } = useFormContext();
  const { user } = useAuth();
  const { setUploadingFiles } = useFormFileUpload();

  const lang = user?.language ?? 'es';
  const thousandSeparator = getThousandSeparator(lang);
  const decimalSeparator = getDecimalSeparator(lang);

  const { required, inputType, options, rows } = question;

  const requiredRule =
    required && !formFilled ? t('validations:required') : false;

  const phoneCountryCode: CountryCode =
    (question.properties?.defaultCountryCode as CountryCode) ??
    DEFAULT_COUNTRY_CODE;
  const callingCode = getCountryCallingCode(phoneCountryCode);

  const requiredRules = useRules({ requiredWithMessage: requiredRule });
  const integerRules = useRules({
    requiredWithMessage: requiredRule,
    onlyNumber: true,
  });

  const phoneRules = useRules({
    requiredPhoneNumber: required && !formFilled ? callingCode : false,
    phoneNumber: callingCode,
  });

  const parsedChoices = useMemo(
    () =>
      options?.map((option, idx) => ({
        id: idx,
        value: idx.toString(),
        label: option.description,
      })) ?? [],
    [options],
  );

  const renderInputField = () => {
    switch (inputType) {
      case InputType.TEXT:
        return (
          <FormInputClassic
            name={name}
            rules={requiredRules}
            inputProps={{
              disabled: formFilled,
              multiline: true,
              minRows: 1,
              hasCounter: false,
              errorText: t('validations:required'),
              placeholder: t('write_here'),
              maxLength: TEXT_MAX_LENGTH,
            }}
          />
        );

      case InputType.TEXT_AREA:
        return (
          <FormInputClassic
            name={name}
            rules={requiredRules}
            inputProps={{
              disabled: formFilled,
              multiline: true,
              minRows: 3,
              hasCounter: false,
              errorText: t('validations:required'),
              placeholder: t('write_here'),
              maxLength: TEXT_AREA_MAX_LENGTH,
            }}
          />
        );

      case InputType.INTEGER:
        return (
          <FormInputClassic
            name={name}
            rules={integerRules}
            inputProps={{
              disabled: formFilled,
              inputMode: 'numeric',
              hasCounter: false,
              errorText: t('validations:required'),
              maxLength: MAX_INTEGER_LENGTH,
              placeholder: '0',
              transform: {
                input: (value: string) => value?.replace(/[^0-9]/g, '') || '',
              },
            }}
          />
        );

      case InputType.DECIMAL:
      case InputType.FLOAT:
        return (
          <FormInputClassic
            name={name}
            rules={{ required }}
            inputProps={{
              disabled: formFilled,
              step: 0.01,
              inputMode: 'decimal',
              autoComplete: 'off',
              autoCorrect: 'off',
              hasCounter: false,
              errorText: t('validations:required'),
              placeholder: lang === 'en' ? '0.00' : '0,00',
              transform: {
                input: (value: string) =>
                  transformIntegerInput(
                    value,
                    thousandSeparator,
                    decimalSeparator,
                  ),
              },
            }}
          />
        );

      case InputType.DROPDOWN:
        return (
          <FormAutocomplete
            name={name}
            rules={requiredRules}
            options={buildOptionsToDropDownCatalog(
              options?.map(o => o.description) ?? [],
            )}
            autocompleteProps={{
              disabled: formFilled,
              multiple: false,
              isServerFiltered: false,
              placeholder: t('select'),
            }}
          />
        );

      case InputType.MULTIPLE_CHOICE:
        return (
          <Controller
            name={name}
            control={control}
            rules={{
              required: requiredRule,
            }}
            render={() => (
              <InputSelectableList
                name={name}
                isMultipleSelect={question.multipleAnswer ?? false}
                options={parsedChoices}
                disabled={formFilled}
              />
            )}
          />
        );

      case InputType.CHECKBOX:
        return (
          <Controller
            name={name}
            control={control}
            rules={{
              required: requiredRule,
            }}
            render={() => (
              <InputSelectableList
                name={name}
                isMultipleSelect={question.multipleAnswer ?? false}
                options={parsedChoices}
                disabled={formFilled}
              />
            )}
          />
        );

      case InputType.CHECKBOX_GRID:
        return (
          <FormRadioGrid
            name={name}
            options={options}
            rows={rows}
            disabled={formFilled}
            rules={{
              requiredCheckboxGrid: required && !formFilled,
            }}
          />
        );

      case InputType.STAR_RATING:
      case InputType.RATE:
        return (
          <FormRating
            name={name}
            rules={requiredRules}
            inputProps={{ disabled: formFilled }}
          />
        );

      case InputType.DATE:
        return (
          <FormDatePicker
            name={name}
            rules={requiredRules}
            inputProps={{
              disabled: formFilled,
              views: ['year', 'month', 'day'],
              format: 'dd/MM/yyyy',
              fullWidth: true,
            }}
          />
        );

      case InputType.DATE_MMAAAA:
        return (
          <FormDatePicker
            name={name}
            rules={requiredRules}
            inputProps={{
              disabled: formFilled,
              views: ['month', 'year'],
              format: 'MM/yyyy',
              fullWidth: true,
            }}
          />
        );

      case InputType.DATE_MMDDYYYY:
        return (
          <FormDatePicker
            name={name}
            rules={requiredRules}
            inputProps={{
              disabled: formFilled,
              views: ['year', 'month', 'day'],
              format: 'MM/dd/yyyy',
              fullWidth: true,
            }}
          />
        );

      case InputType.TIME:
        return (
          <FormTimePicker
            name={name}
            rules={requiredRules}
            inputProps={{
              disabled: formFilled,
              fullWidth: true,
              minutesStep: 1,
            }}
          />
        );
      case InputType.PHONE:
        return (
          <FormInputPhone
            name={name}
            rules={phoneRules}
            validatePhoneNumber={false}
            disabled={formFilled}
            inputProps={{
              showErrors: true,
              defaultCountry: phoneCountryCode,
            }}
          />
        );

      case InputType.MEDIA:
        return (
          <Controller
            name={name}
            control={control}
            rules={{ required: requiredRule }}
            render={({ field: { onChange, value }, fieldState: { error } }) => (
              <>
                <MediaUploader
                  formValue={value}
                  onChange={onChange}
                  disabled={formFilled}
                  setUploadingFiles={setUploadingFiles}
                  fieldName={name}
                />
                <FieldErrorMessage error={error} />
              </>
            )}
          />
        );
      case InputType.FILE:
        return (
          <Controller
            name={name}
            control={control}
            rules={{ required: requiredRule }}
            render={({ field: { onChange, value }, fieldState: { error } }) => (
              <>
                <FileUploader
                  formValue={value}
                  onChange={onChange}
                  disabled={formFilled}
                  setUploadingFiles={setUploadingFiles}
                  fieldName={name}
                />
                <FieldErrorMessage error={error} />
              </>
            )}
          />
        );
      case InputType.DIGITAL_SIGN:
        return (
          <DigitalSignUploader
            name={name}
            required={required}
            disabled={formFilled}
          />
        );
      case InputType.AUTOCOMPLETE:
        return (
          <AutocompleteInput
            name={name}
            userField={question.userField}
          />
        );

      case InputType.INFO:
        return null;
      default:
        return null;
    }
  };

  return (
    <div id={`field-${name}`}>
      <CardContainer fullWidth>
        <Stack sx={{ gap: 1 }}>
          <QuestionTitle
            name={name}
            title={question.description}
            required={required}
            inputType={question.inputType}
          />
          <QuestionAttachments attachments={question.attachments} />
          {renderInputField()}
        </Stack>
      </CardContainer>
    </div>
  );
};

export default InputFieldWrapper;
