import {isValidEmail, isValidInputTextField, updateStylingError, removeErrorStyling} from "./utils/validation";
import {createEvent} from "./utils/create-event";

const Handlebars = require("hbsfy/runtime");
import userInformationField from '../../components/user-information-field.hbs';

var Wick = window.Wick || {};

Wick.PersonalDetails = {
  UPDATE_PERSONAL_DETAILS_EVENT: 'updatePersonalDetails',
  el: {
    userInformationSection: '.user-information',
    userInformationList: '.user-information__list',
    userForm: '.user-form',
    formRow: '.user-form .form-row',
    emailInput: '#email',
    firstNameInput: '#firstName',
    surnameInput: '#lastName',
    btnEdit: '.user-information .btn__edit',
    btnCancel: '[data-action="cancel-form"]',
    btnSave: '[data-action="save-form"]',
    btnContinue: '[data-action="reset-details"]',
    btnChangePassword: '.btn__change-password',
    formInvalidClass: 'form_invalid',
    notification: '.notification',
    fieldError: '.form-row.form-row_validation-error',
    changePasswordPopup: '#change-password-popup',
    confirmationEmailPopup: '#confirmation-email-popup',
    globalMessage: '.globalMessages',
    newEmailElement: '.new-email',
  },
  errorMessages: {
    errorFirstName: 'Please enter your first name',
    errorSurname: 'Please enter your surname',
    errorEmail: 'Please enter your email address',
  },
  defaultNotificationConfig: {
    container: '.personal-details .globalMessages',
    closeBtn: true,
    noScrolling: true,
  },
  isTradeTypeLabel() {
    return $(Wick.PersonalDetails.el.userForm).find('label:contains("Trade type")').length;
  },
  fieldToLabelMap(name) {
    let currentTradeType = ''
    if (name === 'tradeType') {
      currentTradeType = Wick.PersonalDetails.isTradeTypeLabel()
        ? 'Trade type'
        : 'How would you describe yourself or your main trade';
    }

    const fieldMap = {
      titleCode: 'Title',
      firstName: 'First name',
      lastName: 'Surname',
      email: 'Email address',
      tradeType: currentTradeType,
    };

    return fieldMap[name] || name;
  },
  getFieldsConfigurations: function () {
    return [
      {
        input: Wick.PersonalDetails.el.firstNameInput,
        validator: isValidInputTextField,
        error: Wick.PersonalDetails.errorMessages.errorFirstName
      },
      {
        input: Wick.PersonalDetails.el.surnameInput,
        validator: isValidInputTextField,
        error: Wick.PersonalDetails.errorMessages.errorSurname
      },
      {
        input: Wick.PersonalDetails.el.emailInput,
        validator: isValidEmail,
        error: Wick.PersonalDetails.errorMessages.errorEmail
      }
    ]
  },
  showForm() {
    Wick.PersonalDetails.validateForm();
    $(Wick.PersonalDetails.el.notification).remove();
    $(Wick.PersonalDetails.el.userInformationSection).addClass('d-none');
    $(Wick.PersonalDetails.el.userForm).removeClass('d-none');
  },
  hideForm() {
    $(Wick.PersonalDetails.el.userForm).addClass('d-none');
    $(Wick.PersonalDetails.el.userInformationSection).removeClass('d-none');
  },
  validateInput: function (input, validatorFunction, errorMsg) {
    const value = $(input).val();
    const isValid = validatorFunction(value);
    updateStylingError(input, isValid, errorMsg);

    return isValid;
  },
  validateForm: function() {
    const fields = Wick.PersonalDetails.getFieldsConfigurations();
    let isValid = true;

    fields.forEach(field => {
      let parentElem = $(field.input).closest(Wick.PersonalDetails.el.fieldError);
      if (parentElem.length) {
        removeErrorStyling(parentElem);
      }
      const result = Wick.PersonalDetails.validateInput(field.input, field.validator, field.error);
      isValid = isValid && result;
    });

    return isValid;
  },
  requestToUpdateForm() {
    return new Promise((resolve, reject) => {
      const payloadArray = Wick.LeaveEvent.getState(Wick.PersonalDetails.el.userForm);
      const payloadObject = payloadArray.reduce((acc, { name, value }) => {
        acc[name] = value;
        return acc;
      }, {});
      const eventDetail = {resolve, reject};
      const event = createEvent(Wick.PersonalDetails.UPDATE_PERSONAL_DETAILS_EVENT, payloadObject, eventDetail);
      window.dispatchEvent(event);
    })
      .then((response) => {
        Wick.Notification.show({
          ...Wick.PersonalDetails.defaultNotificationConfig,
          text: response.globalMessage.message,
          type: 'success',
        });
        Wick.LeaveEvent.initialFormState = Wick.LeaveEvent.getState(Wick.PersonalDetails.el.userForm);
        Wick.PersonalDetails.updateUserInformationSection(Wick.LeaveEvent.initialFormState);
        Wick.PersonalDetails.updateFormFields(Wick.LeaveEvent.initialFormState);
        Wick.PersonalDetails.hideForm();
        Wick.PersonalDetails.scrollToElement(Wick.PersonalDetails.el.globalMessage);
      })
      .catch((error) => {
        Wick.Notification.show({
          ...Wick.PersonalDetails.defaultNotificationConfig,
          text: error.globalMessage.message,
          type: 'error',
        });
        Wick.PersonalDetails.handleFieldErrors(error);
        Wick.PersonalDetails.scrollToElement(Wick.PersonalDetails.el.globalMessage);
      });
  },
  handleFieldErrors(error) {
    if (error.fieldErrors && error.fieldErrors.length) {
      error.fieldErrors.forEach((fieldError) => {
        const field = `#${fieldError.field}`;
        updateStylingError(field, false, fieldError.message);
      });
    }
  },
  showConfirmationEmailPopup(currentEmail) {
    const $popup = $(Wick.PersonalDetails.el.confirmationEmailPopup);
    $popup.find(Wick.PersonalDetails.el.newEmailElement).text(currentEmail);
    $popup.modal('show');

    $popup.find(Wick.PersonalDetails.el.btnContinue).off('click').on('click', function () {
      Wick.LeaveEvent.removeLeaveEvent();
      $popup.modal('hide');
      Wick.PersonalDetails.requestToUpdateForm();
    });
  },
  submitForm(event) {
    event.preventDefault();
    Wick.PersonalDetails.trimAndRewriteInputs(Wick.PersonalDetails.el.userForm);

    const currentState = Wick.LeaveEvent.getState(Wick.PersonalDetails.el.userForm);
    const initialEmail = Wick.LeaveEvent.initialFormState.find(field => field.name === 'email')?.value;
    const currentEmail = currentState.find(field => field.name === 'email')?.value;

    if (!Wick.PersonalDetails.hasUnsavedChanges()) {
      Wick.PersonalDetails.hideForm();
      $(Wick.PersonalDetails.el.notification).remove();
      Wick.PersonalDetails.scrollToElement(Wick.PersonalDetails.el.globalMessage);
      return;
    }

    if (Wick.PersonalDetails.validateForm()) {
      if (initialEmail !== currentEmail) {
        Wick.PersonalDetails.showConfirmationEmailPopup(currentEmail);
      } else {
        Wick.PersonalDetails.requestToUpdateForm();
      }
    } else {
      Wick.Notification.show({
        ...Wick.PersonalDetails.defaultNotificationConfig,
        text: 'Please correct the errors below.',
        type: 'error',
      });
      Wick.PersonalDetails.scrollToElement(Wick.PersonalDetails.el.globalMessage);
    }
  },
  updateUserInformationSection(personalDetails) {
    const $userInformationList = $(Wick.PersonalDetails.el.userInformationList);

    if (!$userInformationList.length) return;

    $userInformationList.empty();

    personalDetails.forEach(({ name, value, text }) => {
      const label = Wick.PersonalDetails.fieldToLabelMap(name);
      const textField = text || value
      $userInformationList.append(
        userInformationField({
          label,
          textField,
        })
      );
    });

    Wick.PersonalDetails.hideParentListItemIfLabelExists('CSRFToken');
  },
  updateFormFields(personalDetails) {
    personalDetails.forEach(({ name, value, text }) => {
      const field = document.querySelector(`#${name}`);
      if (field) {
        if (field.tagName === 'INPUT') {
          field.value = text || value || '';
          field.setAttribute('value', text || value || '');
        } else {
          const options = field.querySelectorAll('option');
          options.forEach(option => {
            if (option.textContent.trim() === value || option.value === value) {
              option.setAttribute('selected', 'selected');
              field.value = option.value;
            } else {
              option.removeAttribute('selected');
            }
          });
        }
      }
    });
  },
  resetFormToInitialState() {
    Wick.PersonalDetails.hideForm();
    $(Wick.PersonalDetails.el.notification).remove();
    $(Wick.LeaveEvent.el.leavePopup).modal('hide');
    Wick.PersonalDetails.updateFormFields(Wick.LeaveEvent.initialFormState);
  },
  hasUnsavedChanges() {
    const currentState = Wick.LeaveEvent.getState(Wick.PersonalDetails.el.userForm);

    return !_.isEqual(currentState, Wick.LeaveEvent.initialFormState);
  },
  changePasswordHandler(event) {
    const changePasswordUrl = $(Wick.PersonalDetails.el.btnChangePassword).attr('href');

    if (Wick.PersonalDetails.hasUnsavedChanges()) {
      event.preventDefault();
      $(Wick.PersonalDetails.el.changePasswordPopup).modal('show');
      Wick.LeaveEvent.proceedBrowserLeave = true;
      $(Wick.PersonalDetails.el.changePasswordPopup).find(Wick.PersonalDetails.el.btnContinue).off('click').on('click', function () {
        Wick.LeaveEvent.removeLeaveEvent();
        $(Wick.LeaveEvent.el.leavePopup).modal('hide');
        window.location.href = changePasswordUrl;
      });
    } else {
      window.location.href = changePasswordUrl;
    }
  },
  hideParentListItemIfLabelExists(labelText) {
    const label = $(Wick.PersonalDetails.el.userInformationList).find(`label:contains("${labelText}")`);

    if (label.length > 0) {
      label.closest('li').hide();
    }
  },
  scrollToElement(element) {
    const globalMessage = $(element);

    if (globalMessage.length > 0) {
      $('html, body').animate({
        scrollTop: globalMessage.offset().top - 20
      }, 300);
    }
  },
  trimAndRewriteInputs(formSelector) {
    const $form = $(formSelector);

    if (!$form.length) {
      return;
    }

    $form.find('input[type="text"], input[type="email"]').each(function () {
      $(this).val($.trim($(this).val()));
    });
  },
  init: function () {
    Wick.LeaveEvent.bindEvent(
      Wick.PersonalDetails.el.userForm,
      Wick.PersonalDetails.el.btnCancel,
      Wick.PersonalDetails.el.btnContinue,
      Wick.PersonalDetails.resetFormToInitialState
    );

    $(Wick.PersonalDetails.el.btnEdit).on('click', Wick.PersonalDetails.showForm);
    $(Wick.PersonalDetails.el.btnSave).on('click', Wick.PersonalDetails.submitForm);
    $(Wick.PersonalDetails.el.btnChangePassword).on('click', Wick.PersonalDetails.changePasswordHandler);
  }
}

$(document).ready(function () {
  Wick.PersonalDetails.init();
});
