import { compact, get, sortBy } from 'lodash';
import React, { ReactNode, useMemo, useState } from 'react';
import { FormikProps } from 'formik';
import flat from 'flat';
import { format, parse } from 'date-fns';
import { Country, RoomTraveler, Traveler, TravelersFormValues } from '../../booking-wizard/types';
import LabeledInput from '../../booking-wizard/components/labeled-input';
import LabeledSelect from '../../booking-wizard/components/labeled-select';
import PhoneInput from '../../booking-wizard/components/phone-input';
import GenderControl from '../../booking-wizard/features/travelers-form/controls/gender-control';
import TypeAheadInput from '../../booking-wizard/features/travelers-form/type-ahead-input';
import { buildClassName } from '../utils/class-util';
import { CountryItem, PackagingEntry, PackagingEntryPax } from '@qite/tide-client';

export type TravelersFormField = { type: string };
export type AgentOption = { id: number | string; name: string; postalCode?: string; location?: string };
export type TypeAheadOption = { key: string; value: string; text: string };

export interface SharedTravelersSettings {
  countries?: Country[];
  formFields?: TravelersFormField[];
  mainBookerFormFields?: TravelersFormField[];
}

export interface SharedTravelersFormProps {
  formik: FormikProps<TravelersFormValues>;
  translations: any;
  travellersSettings?: SharedTravelersSettings;
  countries?: CountryItem[];
  agents?: AgentOption[];
  bookingType?: string;
  agentAdressId?: number;
  travelersFirstStep?: boolean;
  isUnavailable?: boolean;
  useCompactForm?: boolean;
  showAllCountries?: boolean;
  showAgentSelection?: boolean;
  initialShowAgents?: boolean;
  renderPreviousButton?: () => ReactNode;
  onBookingTypeChange?: (bookingType: string) => void;
}

export function createTraveler(traveler: RoomTraveler, followNumber: { number: number }, personTranslation?: string, isCompact?: boolean): Traveler {
  if (isCompact) {
    return {
      id: traveler.id,
      firstName: personTranslation,
      lastName: `${followNumber.number++}`,
      birthDate: '',
      gender: '',
      age: traveler.age || 30
    } as Traveler;
  }

  return {
    id: traveler.id,
    firstName: '',
    lastName: '',
    birthDate: '',
    gender: ''
  } as Traveler;
}

export function createInitialValuesFromRooms(
  formRooms: { adults: RoomTraveler[]; children: RoomTraveler[] }[],
  startDate?: string,
  agentAdressId?: number,
  personTranslation?: string,
  isCompact?: boolean
): TravelersFormValues {
  const followNumber = { number: 1 };

  const initialValues = {
    startDate,
    rooms: formRooms.map((room) => ({
      adults: room.adults.map((traveler) => createTraveler(traveler, followNumber, personTranslation, isCompact)),
      children: room.children.map((traveler) => createTraveler(traveler, followNumber, personTranslation, isCompact))
    })),
    mainBookerId: -1,
    street: '',
    houseNumber: '',
    box: '',
    zipCode: '',
    place: '',
    country: '',
    phone: '',
    email: '',
    emailConfirmation: '',
    travelAgentId: agentAdressId ?? 0,
    travelAgentName: ''
  } as TravelersFormValues;

  if (initialValues.rooms?.[0]?.adults?.[0]) {
    initialValues.mainBookerId = initialValues.rooms[0].adults[0].id;
  }

  return initialValues;
}

export function createInitialValuesFromEditablePackagingEntry(editablePackagingEntry: PackagingEntry, agentAdressId?: number): TravelersFormValues {
  const pax = editablePackagingEntry?.pax ?? [];
  const rooms = editablePackagingEntry.rooms.map((room) => {
    const roomPax = pax.filter((x: PackagingEntryPax) => room.paxIds.includes(x.id));
    const adults = roomPax.filter((x: PackagingEntryPax) => x.age! >= 18);
    const children = roomPax.filter((x: PackagingEntryPax) => x.age! < 18);
    return {
      adults: adults.map((roomTraveler: PackagingEntryPax) => {
        return {
          id: roomTraveler.id,
          firstName: roomTraveler.firstName ?? '',
          lastName: roomTraveler.lastName ?? '',
          birthDate: roomTraveler.dateOfBirth ? format(new Date(roomTraveler.dateOfBirth), 'yyyy-MM-dd') : '',
          gender: ''
        } as Traveler;
      }),
      children: children.map((roomTraveler: PackagingEntryPax) => {
        return {
          id: roomTraveler.id,
          firstName: roomTraveler.firstName ?? '',
          lastName: roomTraveler.lastName ?? '',
          birthDate: roomTraveler.dateOfBirth ? format(new Date(roomTraveler.dateOfBirth), 'yyyy-MM-dd') : '',
          gender: ''
        } as Traveler;
      })
    };
  });

  const values = createInitialValuesFromRooms(
    rooms.map((room) => ({ adults: room.adults as RoomTraveler[], children: room.children as RoomTraveler[] })),
    editablePackagingEntry?.lines?.[0]?.from,
    agentAdressId
  );

  values.rooms = rooms;
  values.mainBookerId = pax.find((x: any) => x.isMainBooker)?.id ?? rooms[0]?.adults?.[0]?.id ?? -1;

  const address = editablePackagingEntry?.address;

  values.street = address?.street ?? '';
  values.houseNumber = address?.houseNumber ?? '';
  values.box = address?.box ?? '';
  values.zipCode = address?.zipCode ?? '';
  values.place = address?.place ?? '';
  values.country = address?.country ?? '';
  values.phone = address?.phone ?? '';
  values.email = address?.email ?? '';
  values.emailConfirmation = address?.email ?? '';
  values.travelAgentId = address?.travelAgentId ?? agentAdressId ?? 0;

  return values;
}

export function applyTravelersFormValuesToEditablePackagingEntry(editablePackagingEntry: PackagingEntry, values: TravelersFormValues) {
  const travelers = values.rooms.flatMap((room) => [...room.adults, ...room.children]);

  return {
    ...editablePackagingEntry,
    pax: (editablePackagingEntry.pax ?? []).map((pax) => {
      const traveler = travelers.find((x) => x.id === pax.id);
      if (!traveler) return pax;

      return {
        ...pax,
        firstName: traveler.firstName ?? '',
        lastName: traveler.lastName ?? '',
        dateOfBirth: traveler.birthDate || null,
        isMainBooker: traveler.id === values.mainBookerId
      };
    }),
    address: {
      ...editablePackagingEntry.address,
      street: values.street,
      houseNumber: values.houseNumber,
      box: values.box,
      zipCode: values.zipCode,
      place: values.place,
      country: values.country,
      travelAgentId: values.travelAgentId,
      phone: values.phone,
      email: values.email
    }
  };
}

const SharedTravelersForm: React.FC<SharedTravelersFormProps> = ({
  formik,
  translations,
  travellersSettings,
  countries,
  agents,
  bookingType,
  agentAdressId,
  travelersFirstStep = false,
  isUnavailable = false,
  useCompactForm = false,
  showAllCountries = false,
  showAgentSelection = false,
  initialShowAgents = false,
  renderPreviousButton,
  onBookingTypeChange
}) => {
  const [showAgents, setShowAgents] = useState<boolean>(initialShowAgents);

  const typeaheadAgents = useMemo<TypeAheadOption[]>(
    () =>
      sortBy(
        agents?.map((agent) => ({
          key: `${agent.id}`,
          value: `${agent.name}${agent.postalCode || agent.location ? ` (${compact([agent.postalCode, agent.location]).join(' ')})` : ''}`,
          text: `${agent.name}${agent.postalCode || agent.location ? ` (${compact([agent.postalCode, agent.location]).join(' ')})` : ''}`
        })),
        'value'
      ) ?? [],
    [agents]
  );

  const [filteredAgents, setFilteredAgents] = useState<TypeAheadOption[]>(typeaheadAgents);

  const flatErrors: Record<string, string> = flat(formik.errors);
  const errorKeys = Object.keys(flatErrors).filter((key) => get(formik.touched, key));
  const hasVisibleError = (key: string) => get(formik.errors, key) && get(formik.touched, key);

  const mainBooker = formik.values.rooms
    .find((room) => room.adults.find((traveler) => traveler.id === formik.values.mainBookerId))
    ?.adults.find((traveler) => traveler.id === formik.values.mainBookerId);

  const countryOptions = [
    { key: 'empty', value: undefined, label: translations.TRAVELERS_FORM.SELECT_COUNTRY },
    ...(showAllCountries
      ? countries?.map((country) => ({ key: country.iso2, value: country.iso2, label: country.name })) ?? []
      : travellersSettings?.countries?.map((country) => ({ key: country.iso2, value: country.iso2, label: country.name })) ?? [
          { key: 'be', value: 'be', label: translations.TRAVELERS_FORM.COUNTRIES.BELGIUM },
          { key: 'nl', value: 'nl', label: translations.TRAVELERS_FORM.COUNTRIES.NETHERLANDS },
          { key: 'fr', value: 'fr', label: translations.TRAVELERS_FORM.COUNTRIES.FRANCE }
        ])
  ];

  const handleMainBookerChange: React.FormEventHandler<HTMLInputElement> = (event) => {
    formik.setFieldValue('mainBookerId', parseInt(event.currentTarget.value, 10));
  };

  const handleAgentChange = (value: string) => {
    setFilteredAgents(typeaheadAgents.filter((x) => x.value.toLocaleLowerCase().indexOf(value.toLocaleLowerCase()) > -1));
    formik.setFieldValue('travelAgentName', value);
  };

  const handleAgentSelect = (key: string) => {
    const agent = typeaheadAgents.find((x) => x.key === key);

    formik.setValues({
      ...formik.values,
      travelAgentId: Number(agent?.key),
      travelAgentName: agent?.value ?? ''
    });

    onBookingTypeChange?.(agentAdressId && agentAdressId !== 0 ? 'b2b' : 'b2b2c');
  };

  const handleAgentClear = () => {
    formik.setValues({ ...formik.values, travelAgentId: 0, travelAgentName: '' });
    onBookingTypeChange?.('b2c');
  };

  const toggleAgent = (value: boolean) => {
    setShowAgents(value);
    if (!value) {
      handleAgentClear();
      setFilteredAgents([]);
    }
  };

  const handleAddTraveler = (roomIndex: number) => {
    const rooms = [...formik.values.rooms];
    const newAdult = { id: Date.now(), firstName: '', lastName: '', birthDate: '', gender: '' } as Traveler;
    rooms[roomIndex] = { ...rooms[roomIndex], adults: [...rooms[roomIndex].adults, newAdult] };
    formik.setFieldValue('rooms', rooms);
  };

  const handleRemoveTraveler = (roomIndex: number, travelerIndex: number) => {
    const rooms = [...formik.values.rooms];
    const adults = [...rooms[roomIndex].adults];
    if (adults.length <= 1) return;

    adults.splice(travelerIndex, 1);
    rooms[roomIndex] = { ...rooms[roomIndex], adults };
    formik.setFieldValue('rooms', rooms);
  };

  const handleAddRoom = () => {
    const rooms = [...formik.values.rooms];
    rooms.push({ adults: [{ id: Date.now(), firstName: '', lastName: '', birthDate: '', gender: '' } as Traveler], children: [] });
    formik.setFieldValue('rooms', rooms);
  };

  const handleRemoveRoom = (roomIndex: number) => {
    const rooms = [...formik.values.rooms];
    rooms.splice(roomIndex, 1);
    formik.setFieldValue('rooms', rooms);
  };

  const renderGenderControl = (name: string, value: Traveler) => (
    <div className={buildClassName(['form__group', hasVisibleError(name) && 'form__group--error'])}>
      <label className="form__label">{translations.TRAVELERS_FORM.GENDER_ID} *</label>
      <div className="radiobutton-group">
        {[
          ['m', translations.TRAVELERS_FORM.MALE_GENDER],
          ['f', translations.TRAVELERS_FORM.FEMALE_GENDER]
        ].map(([gender, label]) => (
          <div className="radiobutton" key={gender}>
            <label className="radiobutton__label">
              <input
                type="radio"
                className="radiobutton__input"
                name={name}
                onChange={formik.handleChange}
                onBlur={formik.handleBlur}
                value={gender}
                checked={value.gender === gender}
              />
              {label}
            </label>
          </div>
        ))}
      </div>
    </div>
  );

  const getControl = (type: string, value: Traveler, name: string) => {
    switch (type) {
      case 'gender':
        return <GenderControl translations={translations} value={value} formik={formik} name={name} />;
      case 'firstName':
        return (
          <LabeledInput
            hasError={hasVisibleError(name)}
            extraClassName="form__group--md-33"
            label={translations.TRAVELERS_FORM.FIRST_NAME}
            required
            name={name}
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={value.firstName}
          />
        );
      case 'lastName':
        return (
          <LabeledInput
            hasError={hasVisibleError(name)}
            extraClassName="form__group--md-33"
            label={translations.TRAVELERS_FORM.LAST_NAME}
            required
            name={name}
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={value.lastName}
          />
        );
      case 'birthDate':
        return (
          <LabeledInput
            type="date"
            hasError={hasVisibleError(name)}
            extraClassName="form__group--md-33"
            label={translations.TRAVELERS_FORM.BIRTHDATE}
            required
            name={name}
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={value.birthDate}
          />
        );
      case 'country':
        return (
          <LabeledSelect
            hasError={hasVisibleError('country')}
            label={translations.TRAVELERS_FORM.COUNTRY}
            required
            name="country"
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={formik.values.country}
            options={countryOptions}
          />
        );
      case 'phone':
        return (
          <PhoneInput
            countries={travellersSettings?.countries ?? []}
            countryIso2={formik.values.country}
            hasError={hasVisibleError('phone')}
            label={translations.TRAVELERS_FORM.PHONE}
            required
            name="phone"
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={formik.values.phone}
          />
        );
      case 'email':
        return (
          <>
            <LabeledInput
              type="email"
              hasError={hasVisibleError('email')}
              extraClassName="form__group--md-33"
              label={translations.TRAVELERS_FORM.EMAIL}
              required
              name="email"
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              value={formik.values.email}
            />
            <LabeledInput
              type="email"
              hasError={hasVisibleError('emailConfirmation')}
              extraClassName="form__group--md-33"
              label={translations.TRAVELERS_FORM.REPEAT_EMAIL}
              required
              name="emailConfirmation"
              onChange={formik.handleChange}
              onBlur={formik.handleBlur}
              value={formik.values.emailConfirmation}
            />
          </>
        );
      case 'street':
        return (
          <LabeledInput
            hasError={hasVisibleError('street')}
            extraClassName="form__group--50 form__group--sm-60"
            label={translations.TRAVELERS_FORM.STREET}
            required
            name="street"
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={formik.values.street}
          />
        );

      case 'houseNumber':
        return (
          <LabeledInput
            hasError={hasVisibleError('houseNumber')}
            extraClassName="form__group--30 form__group--sm-20"
            label={translations.TRAVELERS_FORM.HOUSE_NUMBER}
            required
            name="houseNumber"
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={formik.values.houseNumber}
          />
        );

      case 'box':
        return (
          <LabeledInput
            hasError={hasVisibleError('box')}
            extraClassName="form__group--20"
            label={translations.TRAVELERS_FORM.POST_BOX}
            name="box"
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={formik.values.box}
          />
        );

      case 'zipCode':
        return (
          <LabeledInput
            hasError={hasVisibleError('zipCode')}
            extraClassName="form__group--40 form__group--sm-20"
            label={translations.TRAVELERS_FORM.ZIPCODE}
            required
            name="zipCode"
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={formik.values.zipCode}
          />
        );

      case 'place':
        return (
          <LabeledInput
            hasError={hasVisibleError('place')}
            extraClassName="form__group--60 form__group--sm-40"
            label={translations.TRAVELERS_FORM.CITY}
            required
            name="place"
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={formik.values.place}
          />
        );
      default:
        return null;
    }
  };

  const renderRoomLabel = (room: TravelersFormValues['rooms'][number]) =>
    compact([
      room.adults.length,
      room.adults.length === 1 && ` ${translations.TRAVELERS_FORM.ADULT}`,
      room.adults.length > 1 && ` ${translations.TRAVELERS_FORM.ADULTS}`,
      room.adults?.length && room.children?.length && ', ',
      room.children.length,
      room.children.length === 1 && ` ${translations.TRAVELERS_FORM.CHILD}`,
      room.children.length > 1 && ` ${translations.TRAVELERS_FORM.CHILDREN}`
    ]).join('');

  const renderTravelerFields = (travelerValues: Traveler, namePrefix: string, isAdult: boolean, roomIndex: number, travelerIndex: number) => {
    if (useCompactForm) {
      return (
        <div className="form__row">
          <LabeledInput
            hasError={hasVisibleError(`${namePrefix}.age`)}
            extraClassName="form__group--md-33"
            label={translations.TRAVELERS_FORM.AGE}
            required
            name={`${namePrefix}.age`}
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={travelerValues.age}
          />
        </div>
      );
    }

    if (travellersSettings?.formFields?.length) {
      return (
        <div className="travelers-form__grid">
          {travellersSettings.formFields.map((field, index) => (
            <div key={index} className={`control control--${field.type}`}>
              {getControl(field.type, travelerValues, `${namePrefix}.${field.type}`)}
            </div>
          ))}
        </div>
      );
    }

    return (
      <>
        <div className="form__row">{renderGenderControl(`${namePrefix}.gender`, travelerValues)}</div>
        <div className="form__row">
          <LabeledInput
            hasError={hasVisibleError(`${namePrefix}.firstName`)}
            extraClassName="form__group--md-33"
            label={translations.TRAVELERS_FORM.FIRST_NAME}
            required
            name={`${namePrefix}.firstName`}
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={travelerValues.firstName}
          />
          <LabeledInput
            hasError={hasVisibleError(`${namePrefix}.lastName`)}
            extraClassName="form__group--md-33"
            label={translations.TRAVELERS_FORM.LAST_NAME}
            required
            name={`${namePrefix}.lastName`}
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={travelerValues.lastName}
          />
          <LabeledInput
            type="date"
            hasError={hasVisibleError(`${namePrefix}.birthDate`)}
            extraClassName="form__group--md-33"
            label={translations.TRAVELERS_FORM.BIRTHDATE}
            required
            name={`${namePrefix}.birthDate`}
            onChange={formik.handleChange}
            onBlur={formik.handleBlur}
            value={travelerValues.birthDate}
          />
        </div>
        {travelersFirstStep && isAdult && formik.values.rooms[roomIndex].adults.length > 1 && (
          <button type="button" className="cta cta--secondary" onClick={() => handleRemoveTraveler(roomIndex, travelerIndex)}>
            {translations.TRAVELERS_FORM.REMOVE_TRAVELER}
          </button>
        )}
      </>
    );
  };

  return (
    <form
      className="form form__travelers"
      name="booking--travellers"
      id="booking--travellers"
      noValidate
      onSubmit={formik.handleSubmit}
      onReset={formik.handleReset}>
      <div className="form__travelers__wrapper">
        {formik.values.rooms.map((room, roomIndex) => (
          <div key={roomIndex}>
            {formik.values.rooms.length > 1 && (
              <div className="form__region">
                <div className="form__region-header">
                  <h5 className="form__region-heading">
                    {translations.SHARED.ROOM} {roomIndex + 1}
                  </h5>
                  <p className="form__region-label">{renderRoomLabel(room)}</p>
                </div>
                {!useCompactForm && travelersFirstStep && formik.values.rooms.length > 1 && (
                  <button type="button" className="cta cta--secondary" onClick={() => handleRemoveRoom(roomIndex)}>
                    Verwijder reisgezelschap
                  </button>
                )}
              </div>
            )}

            {room.adults.map((travelerValues, index) => (
              <div className="form__region" key={travelerValues.id}>
                <div className="form__region-header">
                  <h5 className="form__region-heading">
                    {translations.TRAVELERS_FORM.TRAVELER} {index + 1}
                  </h5>
                  <p className="form__region-label">{translations.TRAVELERS_FORM.ADULT}</p>
                  <div className="radiobutton">
                    <label className="radiobutton__label">
                      <input
                        type="radio"
                        name="mainBookerId"
                        onChange={handleMainBookerChange}
                        onBlur={formik.handleBlur}
                        value={travelerValues.id}
                        checked={formik.values.mainBookerId === travelerValues.id}
                        className="radiobutton__input"
                      />
                      {translations.TRAVELERS_FORM.MAIN_BOOKER}
                    </label>
                  </div>
                </div>
                {renderTravelerFields(travelerValues, `rooms[${roomIndex}].adults[${index}]`, true, roomIndex, index)}
              </div>
            ))}

            {room.children.map((travelerValues, index) => (
              <div className="form__region" key={travelerValues.id}>
                <div className="form__region-header">
                  <h5 className="form__region-heading">
                    {translations.TRAVELERS_FORM.TRAVELER} {room.adults.length + index + 1}
                  </h5>
                  <p className="form__region-label">{translations.TRAVELERS_FORM.CHILD}</p>
                </div>
                {renderTravelerFields(travelerValues, `rooms[${roomIndex}].children[${index}]`, false, roomIndex, index)}
              </div>
            ))}

            {!useCompactForm && travelersFirstStep && (
              <div className="form__region">
                <button type="button" className="cta cta--select" onClick={() => handleAddTraveler(roomIndex)}>
                  {translations.TRAVELERS_FORM.ADD_TRAVELER}
                </button>
              </div>
            )}
          </div>
        ))}

        {!useCompactForm && (bookingType !== 'b2b' || travellersSettings?.mainBookerFormFields?.length) ? (
          <div className="form__region">
            <div className="form__region-header">
              <h5 className="form__region-heading">{translations.TRAVELERS_FORM.MAIN_BOOKER}</h5>
              <p className="form__region-label">
                {compact([
                  compact([mainBooker?.firstName, mainBooker?.lastName]).join(' '),
                  mainBooker?.birthDate && format(parse(mainBooker.birthDate, 'yyyy-MM-dd', new Date()), 'dd-MM-yyyy')
                ]).join(', ')}
              </p>
            </div>
            {travellersSettings?.mainBookerFormFields?.length ? (
              <div className="main-booker-form__grid">
                {travellersSettings.mainBookerFormFields.map((field, index) => (
                  <div key={index} className={`control control--${field.type}`}>
                    {getControl(field.type, {} as Traveler, field.type)}
                  </div>
                ))}
              </div>
            ) : (
              <>
                <div className="form__twocolumn">
                  <div className="form__twocolumn-column">
                    <div className="form__row">
                      <LabeledInput
                        hasError={hasVisibleError('street')}
                        extraClassName="form__group--50 form__group--sm-60"
                        label={translations.TRAVELERS_FORM.STREET}
                        required
                        name="street"
                        onChange={formik.handleChange}
                        onBlur={formik.handleBlur}
                        value={formik.values.street}
                      />
                      <LabeledInput
                        hasError={hasVisibleError('houseNumber')}
                        extraClassName="form__group--30 form__group--sm-20"
                        label={translations.TRAVELERS_FORM.HOUSE_NUMBER}
                        required
                        name="houseNumber"
                        onChange={formik.handleChange}
                        onBlur={formik.handleBlur}
                        value={formik.values.houseNumber}
                      />
                      <LabeledInput
                        hasError={hasVisibleError('box')}
                        extraClassName="form__group--20"
                        label={translations.TRAVELERS_FORM.POST_BOX}
                        name="box"
                        onChange={formik.handleChange}
                        onBlur={formik.handleBlur}
                        value={formik.values.box}
                      />
                    </div>
                  </div>
                  <div className="form__twocolumn-column">
                    <div className="form__row">
                      <LabeledInput
                        hasError={hasVisibleError('zipCode')}
                        extraClassName="form__group--40 form__group--sm-20"
                        label={translations.TRAVELERS_FORM.ZIPCODE}
                        required
                        name="zipCode"
                        onChange={formik.handleChange}
                        onBlur={formik.handleBlur}
                        value={formik.values.zipCode}
                      />
                      <LabeledInput
                        hasError={hasVisibleError('place')}
                        extraClassName="form__group--60 form__group--sm-40"
                        label={translations.TRAVELERS_FORM.CITY}
                        required
                        name="place"
                        onChange={formik.handleChange}
                        onBlur={formik.handleBlur}
                        value={formik.values.place}
                      />
                      <LabeledSelect
                        hasError={hasVisibleError('country')}
                        extraClassName="form__group--sm-40"
                        label={translations.TRAVELERS_FORM.COUNTRY}
                        required
                        name="country"
                        onChange={formik.handleChange}
                        onBlur={formik.handleBlur}
                        value={formik.values.country}
                        options={countryOptions}
                      />
                    </div>
                  </div>
                </div>
                <div className="form__row">
                  <LabeledInput
                    hasError={hasVisibleError('phone')}
                    extraClassName="form__group--md-33"
                    label={translations.TRAVELERS_FORM.PHONE}
                    required
                    name="phone"
                    onChange={formik.handleChange}
                    onBlur={formik.handleBlur}
                    value={formik.values.phone}
                  />
                  <LabeledInput
                    type="email"
                    hasError={hasVisibleError('email')}
                    extraClassName="form__group--md-33"
                    label={translations.TRAVELERS_FORM.EMAIL}
                    required
                    name="email"
                    onChange={formik.handleChange}
                    onBlur={formik.handleBlur}
                    value={formik.values.email}
                  />
                  <LabeledInput
                    type="email"
                    hasError={hasVisibleError('emailConfirmation')}
                    extraClassName="form__group--md-33"
                    label={translations.TRAVELERS_FORM.REPEAT_EMAIL}
                    required
                    name="emailConfirmation"
                    onChange={formik.handleChange}
                    onBlur={formik.handleBlur}
                    value={formik.values.emailConfirmation}
                  />
                </div>
              </>
            )}
          </div>
        ) : !useCompactForm ? (
          <div className="form__region">
            <div className="form__row">
              <LabeledInput
                hasError={hasVisibleError('phone')}
                extraClassName="form__group--md-33"
                label={translations.TRAVELERS_FORM.PHONE}
                required
                name="phone"
                onChange={formik.handleChange}
                onBlur={formik.handleBlur}
                value={formik.values.phone}
              />
            </div>
          </div>
        ) : null}

        {!useCompactForm && showAgentSelection && (
          <div className="form__region">
            <div className="form__region-header">
              <h5 className="form__region-heading">{translations.TRAVELERS_FORM.BOOK_WITH_AGENT}</h5>
              <div className="checkbox" id="cbxChooseOffice">
                <label className="checkbox__label">
                  <input
                    type="checkbox"
                    name="booking--mainbooker"
                    checked={showAgents}
                    onChange={() => toggleAgent(!showAgents)}
                    className="checkbox__input"
                  />
                  {translations.TRAVELERS_FORM.CHOOSE_OFFICE}
                </label>
              </div>
            </div>
            {showAgents && (
              <div className="form__row form__row--choose-office">
                <div className={buildClassName(['form__group', 'form__group--icon', hasVisibleError('travelAgentId') && 'form__group--error'])}>
                  <TypeAheadInput
                    value={formik.values.travelAgentName}
                    options={filteredAgents}
                    onChange={handleAgentChange}
                    onSelect={handleAgentSelect}
                    onClear={handleAgentClear}
                    name="travelAgentName"
                    placeholder={translations.TRAVELERS_FORM.CHOOSE_AGENT_PLACEHOLDER}
                  />
                </div>
              </div>
            )}
          </div>
        )}
      </div>

      {!useCompactForm && errorKeys.length > 0 && (
        <div className="form__region form__region--errors">
          <div className="form__row">
            <div className="form__group">
              <p className="form__error-heading">{translations.TRAVELERS_FORM.VALIDATION_MESSAGE}:</p>
              <ul className="list">
                {errorKeys.map((key) => (
                  <li key={key}>{get(flatErrors, key)}</li>
                ))}
              </ul>
            </div>
          </div>
        </div>
      )}

      {travelersFirstStep && (
        <div className="booking__navigator">
          <button type="button" className="cta cta--select" onClick={handleAddRoom}>
            {translations.TRAVELERS_FORM.ADD_ROOM}
          </button>
        </div>
      )}

      <div className="booking__navigator">
        {renderPreviousButton?.()}
        <button type="submit" title={translations.STEPS.NEXT} className={'cta' + (isUnavailable ? ' cta--disabled' : '')}>
          {translations.STEPS.NEXT}
        </button>
      </div>
    </form>
  );
};

export default SharedTravelersForm;
