import React, { FC, useState } from 'react';
import Form from '../../blocks/Form';
import Input from '../../blocks/Input';
import InputTel from '../InputTel';
import css from './index.module.css';
import 'font-awesome/css/font-awesome.min.css';
import './index.css';
import PlacesAutocomplete, {
  geocodeByAddress,
} from 'react-places-autocomplete';
import {
  autocompleteDebounce,
  getCity,
  getStreetName,
  getStreetNumber,
  getZipCode,
  renderAutocomplete,
} from '../../helpers/addressHelper';
import ToolTipModal from '../../blocks/ToolTipModal';
import classNames from 'classnames';

export interface FormCustomerDetailsValues {
  firstName: string;
  lastName: string;
  emailAddress: string;
  street: string;
  streetNr: string;
  zip: string;
  city: string;
  phoneNumber: {
    isValid: boolean;
    number: string;
    internationalNumber?: string;
  };
  company: string;
  countryCode: string;
  country: string;
  additional: string;
}

export interface FormCustomerDetailsLabels {
  firstName: string;
  lastName: string;
  emailAddress: string;
  phoneNumber: string;
  street: string;
  streetNr: string;
  zip: string;
  city: string;
  company: string;
  additional: string;
  phoneTooltip: string;
  emailTooltip: string;
  country: string;
}

export interface FormCustomerDetailsErrors {
  firstName?: string;
  lastName?: string;
  emailAddress?: string;
  phoneNumber?: {
    isValid: boolean;
    number: string;
  };
  street: string;
  streetNr: string;
  zip: string;
  city: string;
  company?: string;
  additional: string;
}

export interface FormCustomerDetailsTouched {
  [key: string]: unknown;
}

export interface FormCustomerDetailsProps {
  values: FormCustomerDetailsValues;
  touched: FormCustomerDetailsTouched;
  errors: FormCustomerDetailsErrors;
  labels: FormCustomerDetailsLabels;
  handleChange: (e) => void;
  handleBlur: (e) => void;
  status?: {
    msg: string;
  };
  setFieldValue: (field, value) => void;
  setFieldTouched: (field, touched) => void;
  region: string;
  deviceType?: string;
  checkIfKeyBoardOpen?: (e) => void;
  isLoggedIn?: boolean;
  disableToolTips: boolean;
}

const FormCustomerDetails: FC<FormCustomerDetailsProps> = ({
  values,
  touched,
  errors,
  handleChange,
  handleBlur,
  labels,
  status,
  setFieldValue,
  setFieldTouched,
  region,
  checkIfKeyBoardOpen,
  isLoggedIn,
  disableToolTips,
}) => {
  const formRegisterclassNames = classNames({
    [css.formRegister__input]: true,
    [css.formRegister__inputFlex]: true,
  });
  const [isAutocomplete, setAutocomplete] = useState('');

  const handleSelect = async (value): Promise<void> => {
    const results = await geocodeByAddress(value);
    const addressArray = results[0].address_components;
    const cityName = getCity(addressArray);
    const zip = getZipCode(addressArray);
    const streetName = getStreetName(addressArray);
    const streetNumber = getStreetNumber(addressArray);

    if (cityName) setFieldValue('city', cityName);
    if (zip) setFieldValue('zip', zip);
    if (cityName) setFieldValue('street', streetName);
    setFieldValue('streetNr', streetNumber ? streetNumber : values.streetNr);

    // Delay validation because value is no set yet
    setTimeout(() => {
      if (cityName) setFieldTouched('city', true);
      if (zip) setFieldTouched('zip', true);
      if (streetName) setFieldTouched('street', true);
      if (streetNumber) setFieldTouched('streetNr', true);
    });
  };

  const handleSelectValue = async (value): Promise<void> => {
    const results = await geocodeByAddress(value);
    const addressArray = results[0].address_components;
    const cityName = getCity(addressArray);
    const zip = getZipCode(addressArray);

    if (cityName) setFieldValue('city', cityName);
    if (zip) setFieldValue('zip', zip);

    setTimeout(() => {
      if (cityName) setFieldTouched('city', true);
      if (zip) setFieldTouched('zip', true);
    });
  };

  const searchOptionsStreet = {
    componentRestrictions: {
      country: [region],
    },
    types: ['geocode'],
  };

  const searchOptions = {
    componentRestrictions: {
      country: [region],
    },
    types: ['(regions)'],
  };

  const mapsAvailable = (): boolean => {
    return !!window['google'];
  };

  return (
    <Form novalidate>
      <div className={css.formRegister__input}>
        <Input
          style={'booking'}
          name="firstName"
          type="text"
          label={labels.firstName}
          required
          onChange={handleChange}
          onBlur={handleBlur}
          value={values.firstName}
          error={touched.firstName && errors.firstName}
          isKeyBoardOpen={checkIfKeyBoardOpen}
        />
      </div>

      <div className={css.formRegister__input}>
        <Input
          style={'booking'}
          name="lastName"
          autocomplete="family-name"
          type="text"
          label={labels.lastName}
          required
          onChange={handleChange}
          onBlur={handleBlur}
          value={values.lastName}
          error={touched.lastName && errors.lastName}
          isKeyBoardOpen={checkIfKeyBoardOpen}
        />
      </div>

      <div className={css.formRegister__input}>
        <Input
          style={'booking'}
          name="company"
          isOptionalDisplay={true}
          type="text"
          label={labels.company}
          onChange={handleChange}
          onBlur={handleBlur}
          value={values.company}
          error={touched.company && errors.company}
          isKeyBoardOpen={checkIfKeyBoardOpen}
        />
      </div>

      <div className={css.formRegister__helper}>
        <div className={formRegisterclassNames}>
          <InputTel
            variant={'booking'}
            name="phoneNumber"
            label={labels.phoneNumber}
            onChange={handleChange}
            onBlur={handleBlur}
            value={values.phoneNumber}
            error={
              touched.phoneNumber &&
              errors.phoneNumber && {
                number: errors.phoneNumber.number,
                isValid: errors.phoneNumber.isValid,
              }
            }
            defaultCountry={
              values.countryCode === 'uk' ? 'gb' : values.countryCode
            }
          />
        </div>
        {!disableToolTips && (
          <ToolTipModal
            title={labels.phoneNumber}
            description={labels.phoneTooltip}
            iconClass={css.formRegister__phonehelperIcon}
          />
        )}
      </div>

      <div className={css.formRegister__helper}>
        <div className={formRegisterclassNames}>
          <Input
            style={'booking'}
            name="emailAddress"
            type="email"
            label={labels.emailAddress}
            required
            onChange={handleChange}
            onBlur={handleBlur}
            value={values.emailAddress}
            error={touched.emailAddress && errors.emailAddress}
            isKeyBoardOpen={checkIfKeyBoardOpen}
            disabled={isLoggedIn}
          />
        </div>
        {!disableToolTips && (
          <ToolTipModal
            title={labels.emailAddress}
            description={labels.emailTooltip}
            iconClass={css.formRegister__emailhelperIcon}
          />
        )}
      </div>

      <div className={css.formRegister__inputStreet}>
        {mapsAvailable() && (
          <PlacesAutocomplete
            debounce={500}
            value={values.street}
            onChange={(val): void => {
              autocompleteDebounce(
                isAutocomplete,
                setAutocomplete,
                'street',
                500,
              );
              setFieldValue('street', val);
              setTimeout(() => setFieldTouched('street', true));
            }}
            onSelect={handleSelect}
            searchOptions={searchOptionsStreet}
            shouldFetchSuggestions={isAutocomplete == 'street'}
          >
            {({
              getInputProps,
              suggestions,
              getSuggestionItemProps,
            }): JSX.Element => {
              return renderAutocomplete(
                checkIfKeyBoardOpen,
                getInputProps,
                suggestions,
                getSuggestionItemProps,
                labels.street,
                values.street,
                touched.street,
                errors.street,
                setFieldTouched,
                'text',
                'street',
                'street-address',
              );
            }}
          </PlacesAutocomplete>
        )}

        <div className={css.formRegister__input}>
          <Input
            style={'booking'}
            name="streetNr"
            autocomplete="street-address"
            type="text"
            label={labels.streetNr}
            required
            onChange={handleChange}
            onBlur={handleBlur}
            value={values.streetNr}
            error={touched.streetNr && errors.streetNr}
            isKeyBoardOpen={checkIfKeyBoardOpen}
          />
        </div>
      </div>

      <div className={css.formRegister__input}>
        <Input
          style={'booking'}
          name="additional"
          type="text"
          label={labels.additional}
          isOptionalDisplay={true}
          onChange={handleChange}
          onBlur={handleBlur}
          value={values.additional}
          error={touched.additional && errors.additional}
          isKeyBoardOpen={checkIfKeyBoardOpen}
        />
      </div>

      <div className={css.formRegister__inputCity}>
        {mapsAvailable() && (
          <PlacesAutocomplete
            debounce={500}
            value={values.zip}
            onChange={(val): void => {
              autocompleteDebounce(isAutocomplete, setAutocomplete, 'zip', 500);
              setFieldValue('zip', val);
              setTimeout(() => setFieldTouched('zip', true));
            }}
            onSelect={handleSelectValue}
            searchOptions={searchOptions}
            shouldFetchSuggestions={isAutocomplete == 'zip'}
          >
            {({
              getInputProps,
              suggestions,
              getSuggestionItemProps,
            }): JSX.Element => {
              return renderAutocomplete(
                checkIfKeyBoardOpen,
                getInputProps,
                suggestions,
                getSuggestionItemProps,
                labels.zip,
                values.zip,
                touched.zip,
                errors.zip,
                setFieldTouched,
                'text',
                'zip',
                'postal-code',
              );
            }}
          </PlacesAutocomplete>
        )}

        {mapsAvailable() && (
          <PlacesAutocomplete
            debounce={500}
            value={values.city}
            onChange={(val): void => {
              autocompleteDebounce(
                isAutocomplete,
                setAutocomplete,
                'city',
                500,
              );
              setFieldValue('city', val);
              setTimeout(() => setFieldTouched('city', true));
            }}
            onSelect={handleSelectValue}
            searchOptions={searchOptions}
            shouldFetchSuggestions={isAutocomplete == 'city'}
          >
            {({
              getInputProps,
              suggestions,
              getSuggestionItemProps,
            }): JSX.Element => {
              return renderAutocomplete(
                checkIfKeyBoardOpen,
                getInputProps,
                suggestions,
                getSuggestionItemProps,
                labels.city,
                values.city,
                touched.city,
                errors.city,
                setFieldTouched,
                'text',
                'city',
                'locality',
              );
            }}
          </PlacesAutocomplete>
        )}
      </div>

      {status && status.msg && (
        <div className={css.formRegister__messages}>{status.msg}</div>
      )}
    </Form>
  );
};

export default FormCustomerDetails;
