import { createAppLocalVue, waitNT } from '@/../tests/utils' // should be the first to implement default mocks
import PreferredContact from '../landing/components/PreferredContact'
import { mount } from '@vue/test-utils'
import flushPromises from 'flush-promises'
import { loggedOutStore } from '@/../tests/factories/auth-store'
import store from '@/store'
import router from '@/router'

const localVue = createAppLocalVue()

describe('Login - Landing - Preferred Contact', () => {
  let wrapper, getCode, postCode

  beforeEach(async () => {
    getCode = jest.fn().mockImplementation(async () => {
      wrapper.setData({
        getVerificationResponseData: {
          sent: true,
        },
      })

      await flushPromises()

      return Promise.resolve(true)
    })
    postCode = jest.fn().mockImplementation(async () => {
      wrapper.setData({
        postVerificationResponseData: {
          sent: true,
        },
      })

      await flushPromises()

      return Promise.resolve(true)
    })

    wrapper = mount(PreferredContact, {
      localVue,
      store,
      router,
      methods: {
        getCode,
        postCode,
        initPhoneMixin: jest.fn(),
        loadCountries: jest.fn(),
        loadMasterDataKeys: jest.fn(),
      },
      data: () => ({
        resetErrorStatus: null,
        errorsBreakup: [],
        responseData: {},
        getVerificationResponseData: {},
        postVerificationResponseData: {},
        loggedInUser: {
          id: 1,
        },
      }),
      computed: {
        preferredEmailId: () => 0,
        preferredPhoneId: () => 1,
        getErrorsState() {
          return function() {
            return this.$data.resetErrorStatus
          }
        },
        getErrorsBreakup() {
          return function() {
            return this.$data.errorsBreakup
          }
        },
        getVerificationResponse() {
          return this.$data.getVerificationResponseData
        },
        postVerificationResponse() {
          return this.$data.postVerificationResponseData
        },
        preferredContactOptions: () => () => [
          { value: 0, text: 'mobile' },
          { value: 1, text: 'email' },
        ],
        isLoading: () => () => false,
        resolveMasters: jest.fn().mockImplementation(() => Promise.resolve(true)),
        getCountriesCallCode: () => [{ value: 0, text: 'my' }],
        getLoggedInUser() {
          return this.$data.loggedInUser
        },
      },
      sync: false,
    })

    await flushPromises()
  })

  it('Should display errors', async () => {
    wrapper.setData({
      resetErrorStatus: false,
      errorsBreakup: ['error1'],
    })

    await flushPromises()
    await waitNT(wrapper.vm)

    expect(wrapper.find('.invalid').text()).toContain('error1')
  })

  it('Should validate get verification code fields', async () => {
    wrapper.find({ ref: 'getVerificationCode' }).trigger('click')

    await flushPromises()
    await waitNT(wrapper.vm)

    expect(wrapper.vm.$validator.errors.any()).toBe(true)
  })

  it('should submit when fields are valid for email', async () => {
    wrapper
      .find({ ref: 'preferredContactType' })
      .findAll('input')
      .at(0)
      .trigger('click')

    wrapper.find({ ref: 'email' }).setValue('shiman.dc@gmail.com')
    wrapper.find({ ref: 'getVerificationCode' }).trigger('click')

    await flushPromises()

    expect(getCode).toBeCalledWith({
      user_id: 1,
      type: 'email',
      verification_email: 'shiman.dc@gmail.com',
    })

    await flushPromises()
    await waitNT(wrapper.vm)

    // should be valid with verification code
    wrapper.find({ ref: 'verificationCode' }).setValue('12313123')
    wrapper.find({ ref: 'postVerificationCode' }).trigger('click')

    await flushPromises()
    await waitNT(wrapper.vm)

    expect(postCode).toBeCalledWith({
      user_id: 1,
      preferred_contact_id: 0,
      on_behalf_enrolment: 1,
      type: 'email',
      verification_email: 'shiman.dc@gmail.com',
      verification_code: '12313123',
    })
  })

  it('should submit when fields are valid for mobile', async () => {
    wrapper
      .find({ ref: 'preferredContactType' })
      .findAll('input')
      .at(1)
      .trigger('click')

    await waitNT(wrapper.vm)
    // change the language
    wrapper
      .find({ ref: 'countryCode' })
      .findAll('option')
      .at(0)
      .setSelected()

    wrapper.find({ ref: 'mobile' }).setValue(173312364)
    await waitNT(wrapper.vm)
    wrapper.find({ ref: 'getVerificationCode' }).trigger('click')

    await flushPromises()
    await waitNT(wrapper.vm)

    expect(getCode).toBeCalledWith({
      call_code_id: 0,
      user_id: 1,
      type: 'phone',
      verification_mobile: '173312364',
    })

    await flushPromises()
    await waitNT(wrapper.vm)

    // should be valid with verification code
    wrapper.find({ ref: 'verificationCode' }).setValue('12313123')
    wrapper.find({ ref: 'postVerificationCode' }).trigger('click')

    await flushPromises()
    await waitNT(wrapper.vm)

    expect(postCode).toBeCalledWith({
      user_id: 1,
      call_code_id: 0,
      preferred_contact_id: 1,
      on_behalf_enrolment: 1,
      type: 'phone',
      verification_mobile: '173312364',
      verification_code: '12313123',
    })
  })
})
