<template>
  <ElForm
    ref="registrationForm"
    :model="registrationForm"
    :rules="rules"
    name="register-form"
    label-position="top"
    class="auth-form register"
    @submit.native.prevent="submitRegistration"
  >
    <AuthPageHeader title="Let’s get started by creating an account." />
    <p v-if="showProjectInfo">
      <span id="employer-info">
        When your {{ employerName }} proposal is underwritten, you’ll submit your quote here
      </span><br>
      <span id="carrier-info">
        <strong>Heads up:</strong>
        <!-- eslint-disable-next-line max-len -->
        {{ submittedCarriers }} out of {{ invitedCarriers }} carriers invited have submitted their quotes.
      </span>
    </p>
    <div class="inputs-container">
      <ElFormItem
        for="first-name-input"
        prop="firstName"
        class="first-name-container"
        label="First name"
        size="medium"
        data-test="first name form item"
      >
        <ElInput
          v-model="registrationForm.firstName"
          name="first-name-input"
          data-test="edit first name"
          placeholder="Enter First Name"
          @input="$emit('setUserInfo', { 'first_name': $event })"
        />
      </ElFormItem>

      <ElFormItem
        for="last-name-input"
        prop="lastName"
        class="last-name-container"
        label="Last name"
        size="medium"
        data-test="last name form item"
      >
        <ElInput
          v-model="registrationForm.lastName"
          name="last-name-input"
          data-test="edit last name"
          placeholder="Enter Last Name"
          @input="$emit('setUserInfo', { 'last_name': $event })"
        />
      </ElFormItem>

      <ElFormItem
        prop="role"
        class="role-container"
        label="Role"
        data-test="role form item"
      >
        <ElSelect
          v-model="registrationForm.role"
          placeholder="Select a Role"
          name="role input"
          data-test="edit role"
          @input="$emit('setUserInfo', { role: $event })"
        >
          <ElOption
            v-for="role in roles"
            :key="role"
            class="role-input-option"
            data-test="select role"
            :label="role"
            :value="role"
          />
        </ElSelect>
      </ElFormItem>

      <ElFormItem
        :class="{ 'is-error' : customError }"
        for="email-input"
        prop="email"
        class="email-container"
        label="Company email"
        size="medium"
        data-test="email form item"
      >
        <ElInput
          v-model="registrationForm.email"
          name="email-input"
          placeholder="Enter email"
          data-test="edit email"
        />
        <div
          v-if="customError"
          class="el-form-item__error"
          :data-test="`error ${customError}`"
        >
          <template v-if="customError === 'emailTaken'">
            Email has already been taken.
            <RouterLink
              :to="linkForgot"
              v-text="'Reset your password'"
            />.
          </template>
          <template v-else-if="customError === 'notValid'">
            <!-- eslint-disable-next-line max-len -->
            Your company domain isn’t in our system. Make sure you typed your email address correctly.
          </template>
          <template v-else>
            There was a problem processing your request.
          </template>
        </div>
      </ElFormItem>

      <ElFormItem
        for="password-input"
        prop="password"
        class="password-container"
        size="medium"
      >
        <TfPasswordField
          v-model="registrationForm.password"
          label="Create password"
          :is-valid-password.sync="isValidPassword"
        />
      </ElFormItem>
      <div class="btn-group">
        <slot name="ctaSubmit">
          <AppButton
            :is-disabled="btnCreateDisabled"
            name="submit-button"
            type="primary"
            native-type="submit"
            text="Create account"
            data-test="submit account"
            no-branding
          />
        </slot>
      </div>
      <ul class="links-container">
        <RouterLink
          tag="li"
          :to="linkLogin"
        >
          <AppButton
            id="link-account"
            type="primary"
            size="text"
            text="I already have an account."
            data-test="link account"
            no-branding
          />
        </RouterLink>
      </ul>
    </div>
    <AuthPageFooter />
  </ElForm>
</template>

<script>
  export default {
    name: 'AppRegisterForm',
    props: {
      accountService: {
        type: Object,
        default: () => ({}),
      },
      checkInvited: {
        type: Boolean,
        default: false,
      },
      documentId: {
        type: String,
        default: null,
      },
      employerName: {
        type: String,
        default: '',
      },
      invitedCarriers: {
        type: Number,
        default: 0,
      },
      linkForgot: {
        type: [String, Object],
        required: true,
      },
      linkLogin: {
        type: [String, Object],
        required: true,
      },
      linkRegisterConfirmation: {
        type: [String, Object],
        required: true,
      },
      projectId: {
        type: [String, Number],
        default: null,
      },
      showProjectInfo: {
        type: Boolean,
        default: true,
      },
      submittedCarriers: {
        type: Number,
        default: 0,
      },
      userInfo: {
        type: Object,
        default: () => ({}),
      },
    },
    data: (vm) => ({
      customError: null, // 'emailTaken' || 'notValid' || 'generic'
      formErrorMessage: null,
      notInvited: false,
      registrationForm: {
        firstName: vm.userInfo.firstName,
        lastName: vm.userInfo.lastName,
        role: vm.userInfo.role,
        email: '',
        password: '',
      },
      rules: {
        firstName: [
          {
            required: true,
            message: 'Please enter your first name.',
            trigger: 'blur',
          },
        ],
        lastName: [
          {
            required: true,
            message: 'Please enter your last name.',
            trigger: 'blur',
          },
        ],
        role: [
          {
            required: true,
            message: 'Please enter your role.',
            trigger: 'blur',
          },
        ],
        email: [
          {
            required: true,
            type: 'email',
            message: 'Please enter your company email.',
            trigger: 'blur',
          },
          {
            validator: vm.clearError,
            trigger: 'change',
          },
          {
            validator: vm.validateEmail,
            trigger: 'blur',
          },
        ],
      },
      roles: [
        'Executive or Corporate Sponsor',
        'Regional Leader',
        'Sales Executive',
        'Sales Coordinator',
        'Underwriter',
        'Account Manager',
      ],
      isValidPassword: false,
    }),
    computed: {
      /**
       * Evaluate the registration form values to determine if the Create button is disabled.
       *
       * @returns {boolean}
       */
      btnCreateDisabled() {
        return Object.values(this.registrationForm)
          .some((value) => !value) || !this.isValidPassword;
      },
    },
    watch: {
      /**
       * Watching the email field - and updating the vuex store with the new email
       *
       * @param {string} email
       */
      'registrationForm.email': function (email) {
        this.$emit('setUserEmail', email);
        this.$emit('update:email', email);
        this.notInvited = false;

        if (this.customError) {
          this.customError = null;
        }
      },
      /**
       * Watch the "firstName" field to sync with parent component.
       *
       * @param {string} value
       */
      'registrationForm.firstName': function (value) {
        this.$emit('update:firstName', value);
      },
      /**
       * Watch the "lastName" field to sync with parent component.
       *
       * @param {string} value
       */
      'registrationForm.lastName': function (value) {
        this.$emit('update:lastName', value);
      },
      /**
       * Watch the "role" field to sync with parent component.
       *
       * @param {string} value
       */
      'registrationForm.role': function (value) {
        this.$emit('update:role', value);
      },
      /**
       * Watch the "password" field to sync with parent component.
       *
       * @param {string} value
       */
      'registrationForm.password': function (value) {
        this.$emit('update:password', value);
      },
    },
    created() {
      // We want the email address to persist across all login/forgotPW/registration forms
      this.registrationForm.email = this.$route.query.email || this.userInfo.email;
    },
    /* When the component is destroyed we need to remove the event listener we manually added for the error message */
    beforeDestroy() {
      if (this.formErrorMessage) {
        this.formErrorMessage.close();
      }
    },

    methods: {
      /* eslint-disable-next-line jsdoc/require-param */
      /**
       * Clear out any displayed errors
       */
      clearError(rule, value, callback) {
        callback();
      },

      /* eslint-disable-next-line jsdoc/require-param */
      /**
       * Method to validate the email address and see if this user was invited to the project
       */
      validateEmail(rule, value, callback) {
        if (!this.registrationForm.email || !this.checkInvited) {
          callback();

          return;
        }

        this.accountService
          .checkInvitedToProject(this.registrationForm.email, this.projectId)
          .then(() => {
            callback();
          })
          .catch(() => {
            this.notInvited = true;
            callback(new Error('This email is not invited. Ensure you’re using your company email and that it has been invited. Or contact support@threeflow.com.'));
          });
      },

      /**
       * Validate the registrationForm and call the accountService/registerUser method.
       */
      submitRegistration() {
        this.$refs.registrationForm.validate((valid) => {
          if (valid) {
            if (!this.accountService.registerUser) {
              return valid;
            }

            const data = {
              firstName: this.registrationForm.firstName,
              lastName: this.registrationForm.lastName,
              department: this.registrationForm.role,
              email: this.registrationForm.email,
              password: this.registrationForm.password,
              projectId: this.projectId,
            };

            if (this.documentId) {
              data.documentId = this.documentId;
            }

            this.accountService
              .registerUser(data)
              .then(() => {
                this.$router.push(this.linkRegisterConfirmation);
              })
              .catch(({ response }) => {
                const { code, message } = response.data;
                let customError = 'generic';

                // 'emailTaken' || 'notValid' || 'generic'
                if (code === 'INVALID_PARAMS') {
                  if (message === 'Email has already been taken') {
                    customError = 'emailTaken';
                  } else if (message === 'Email is invalid') {
                    customError = 'notValid';
                  }
                }

                this.customError = customError;
              });
          }

          return valid;
        });
      },
    },
  };
</script>
