import { FormikErrors } from 'formik';
import { isEmpty, set } from 'lodash';
import { FormField, TravelersFormValues } from '../../types';
import { CHILD_MAX_AGE } from './travelers-form-slice';
import { format } from '../../../shared/utils/localization-util';

function isValidEmail(email: string) {
  return !/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,24}$/i.test(email);
}

function getAge(birthDateText: string, startDateText: string) {
  var birthDate = new Date(birthDateText);
  var startDate = new Date(startDateText);

  var age = startDate.getFullYear() - birthDate.getFullYear();
  var m = startDate.getMonth() - birthDate.getMonth();
  if (m < 0 || (m === 0 && startDate.getDate() < birthDate.getDate())) {
    age--;
  }
  return age;
}

const validateForm = (
  values: TravelersFormValues,
  agentRequired?: boolean,
  bookingType?: string,
  translations?: any,
  formFields?: FormField[],
  mainBookerFormFields?: FormField[]
) => {
  const errors: FormikErrors<TravelersFormValues> = {};
  const isFormFieldPresent = (type: string) => {
    return formFields?.some((f) => f.type === type) ?? true;
  };
  const isMainBookerFormFieldPresent = (type: string) => {
    return mainBookerFormFields?.some((f) => f.type === type) ?? true;
  };

  const formatTravelerField = (room: number, pax: number, field: string) => {
    return values.rooms.length > 1
      ? format(translations.TRAVELERS_FORM.VALIDATION.TRAVELER_X_FIELD, [room, pax, field])
      : format(translations.TRAVELERS_FORM.VALIDATION.SINGLE_ROOM_TRAVELER_X_FIELD, [pax, field]);
  };
  const formatTravelerIsNoAdult = (room: number, pax: number) => {
    return values.rooms.length > 1
      ? format(translations.TRAVELERS_FORM.VALIDATION.TRAVELER_X_IS_NO_ADULT, [room, pax])
      : format(translations.TRAVELERS_FORM.VALIDATION.SINGLE_ROOM_TRAVELER_X_IS_NO_ADULT, [pax]);
  };
  const formatTravelerIsNoChild = (room: number, pax: number) => {
    return values.rooms.length > 1
      ? format(translations.TRAVELERS_FORM.VALIDATION.TRAVELER_X_IS_NO_CHILD, [room, pax])
      : format(translations.TRAVELERS_FORM.VALIDATION.SINGLE_ROOM_TRAVELER_X_IS_NO_CHILD, [pax]);
  };

  values.rooms.forEach((r, rIndex) =>
    r.adults.forEach((adult, index) => {
      if (isEmpty(adult.gender) && isFormFieldPresent('gender')) {
        set(errors, `rooms[${rIndex}].adults[${index}].gender`, formatTravelerField(rIndex + 1, index + 1, translations.TRAVELERS_FORM.GENDER));
      }

      if (isEmpty(adult.firstName) && isFormFieldPresent('firstName')) {
        set(errors, `rooms[${rIndex}].adults[${index}].firstName`, formatTravelerField(rIndex + 1, index + 1, translations.TRAVELERS_FORM.FIRST_NAME));
      }

      if (isEmpty(adult.lastName) && isFormFieldPresent('lastName')) {
        set(errors, `rooms[${rIndex}].adults[${index}].lastName`, formatTravelerField(rIndex + 1, index + 1, translations.TRAVELERS_FORM.LAST_NAME));
      }

      if (isFormFieldPresent('birthDate')) {
        if (isEmpty(adult.birthDate)) {
          set(errors, `rooms[${rIndex}].adults[${index}].birthDate`, formatTravelerField(rIndex + 1, index + 1, translations.TRAVELERS_FORM.BIRTHDATE));
        } else if (values.startDate) {
          const age = getAge(adult.birthDate, values.startDate);

          if (age <= CHILD_MAX_AGE) {
            set(errors, `rooms[${rIndex}].adults[${index}].birthDate`, formatTravelerIsNoAdult(rIndex + 1, index + 1));
          }
        }
      }
    })
  );

  values.rooms.forEach((r, rIndex) =>
    r.children.forEach((child, index) => {
      if (isEmpty(child.gender) && isFormFieldPresent('gender')) {
        set(
          errors,
          `rooms[${rIndex}].children[${index}].gender`,
          formatTravelerField(rIndex + 1, r.adults.length + index + 1, translations.TRAVELERS_FORM.GENDER)
        );
      }

      if (isEmpty(child.firstName) && isFormFieldPresent('firstName')) {
        set(errors, `children[${index}].firstName`, formatTravelerField(rIndex + 1, r.adults.length + index + 1, translations.TRAVELERS_FORM.FIRST_NAME));
      }

      if (isEmpty(child.lastName) && isFormFieldPresent('lastName')) {
        set(
          errors,
          `rooms[${rIndex}].children[${index}].lastName`,
          formatTravelerField(rIndex + 1, r.adults.length + index + 1, translations.TRAVELERS_FORM.LAST_NAME)
        );
      }

      if (isFormFieldPresent('birthDate')) {
        if (isEmpty(child.birthDate)) {
          set(
            errors,
            `rooms[${rIndex}].children[${index}].birthDate`,
            formatTravelerField(rIndex + 1, r.adults.length + index + 1, translations.TRAVELERS_FORM.BIRTHDATE)
          );
        } else if (values.startDate) {
          const age = getAge(child.birthDate, values.startDate);

          if (age > CHILD_MAX_AGE) {
            set(errors, `rooms[${rIndex}].children[${index}].birthDate`, formatTravelerIsNoChild(rIndex + 1, r.adults.length + index + 1));
          }
        }
      }
    })
  );

  if (values.mainBookerId < 0) {
    errors.mainBookerId = translations.TRAVELERS_FORM.VALIDATION.NO_MAIN_BOOKER_SELECTED;
  }

  if (bookingType != 'b2b' || mainBookerFormFields?.length) {
    if (isEmpty(values.street) && isMainBookerFormFieldPresent('street')) {
      errors.street = format(translations.TRAVELERS_FORM.VALIDATION.MAIN_BOOKER_FIELD, [translations.TRAVELERS_FORM.STREET]);
    }

    if (isEmpty(values.houseNumber) && isMainBookerFormFieldPresent('houseNumber')) {
      errors.houseNumber = format(translations.TRAVELERS_FORM.VALIDATION.MAIN_BOOKER_FIELD, [translations.TRAVELERS_FORM.HOUSE_NUMBER]);
    }

    if (isEmpty(values.zipCode) && isMainBookerFormFieldPresent('zipCode')) {
      errors.zipCode = format(translations.TRAVELERS_FORM.VALIDATION.MAIN_BOOKER_FIELD, [translations.TRAVELERS_FORM.ZIPCODE]);
    }

    if (isEmpty(values.place) && isMainBookerFormFieldPresent('place')) {
      errors.place = format(translations.TRAVELERS_FORM.VALIDATION.MAIN_BOOKER_FIELD, [translations.TRAVELERS_FORM.CITY]);
    }

    if (isMainBookerFormFieldPresent('email')) {
      if (isEmpty(values.email)) {
        errors.email = format(translations.TRAVELERS_FORM.VALIDATION.MAIN_BOOKER_FIELD, [translations.TRAVELERS_FORM.EMAIL]);
      } else if (isValidEmail(values.email)) {
        errors.email = translations.TRAVELERS_FORM.VALIDATION.MAIN_BOOKER_EMAIL_IS_INVALID;
      }

      if (isEmpty(values.emailConfirmation)) {
        errors.emailConfirmation = format(translations.TRAVELERS_FORM.VALIDATION.MAIN_BOOKER_FIELD, [translations.TRAVELERS_FORM.REPEAT_EMAIL]);
      } else if (values.emailConfirmation !== values.email) {
        errors.emailConfirmation = translations.TRAVELERS_FORM.VALIDATION.MAIN_BOOKER_EMAIL_DOES_NOT_MATCH;
      }
    }

    if (isEmpty(values.country) && isMainBookerFormFieldPresent('country')) {
      errors.country = format(translations.TRAVELERS_FORM.VALIDATION.MAIN_BOOKER_FIELD, [translations.TRAVELERS_FORM.COUNTRY]);
    }

    if (isEmpty(values.phone) && isMainBookerFormFieldPresent('phone')) {
      errors.phone = format(translations.TRAVELERS_FORM.VALIDATION.MAIN_BOOKER_FIELD, [translations.TRAVELERS_FORM.PHONE]);
    }
  } else {
    if (isEmpty(values.phone)) {
      errors.phone = format(translations.TRAVELERS_FORM.VALIDATION.MAIN_BOOKER_FIELD, [translations.TRAVELERS_FORM.PHONE]);
    }
  }

  if (agentRequired && !values.travelAgentId) {
    errors.travelAgentId = translations.TRAVELERS_FORM.VALIDATION.AGENT_IS_REQUIRED;
  }

  return errors;
};

export default validateForm;
