import { it, describe, expect, vi, beforeEach, afterEach } from 'vitest'
import { shallowMount, flushPromises } from '@vue/test-utils'
import MySettingsView from '../../../views/MySettingsView.vue'
import { createI18n } from 'vue-i18n'
import axios from 'axios'
import fr from '../../../locales/fr.json'
import Button from '../../../components/Button.vue'
import { updateClipboard } from '../../../utils/copyToClipboard'
import * as copyToClipboardModule from '../../../utils/copyToClipboard'

const i18n = createI18n({
  locale: 'fr',
  fallbackLocale: 'fr',
  globalInjection: true,
  legacy: false,
  messages: {
    fr
  }
})

const mockResponseTokens = [
  {
    description: 'my token',
    generated_at: '2023-05-16T11:08:11.247187+00:00',
    id: 'my-id',
    links: [
      {
        href: 'https://my-link',
        rel: 'self',
        type: 'application/json'
      }
    ]
  }
]

describe('Template', () => {
  describe('When all the tokens list are fetched', () => {
    it('should render all the tokens hidden', async () => {
      vi.spyOn(axios, 'get').mockResolvedValue({ data: mockResponseTokens })
      const wrapper = shallowMount(MySettingsView, {
        global: {
          plugins: [i18n],
          mocks: {
            $t: (msg) => msg
          }
        }
      })
      await flushPromises()
      expect(axios.get).toHaveBeenCalledWith('api/users/me/tokens')
      expect(wrapper.vm.userTokens).toEqual(mockResponseTokens)
      expect(wrapper.html()).contains('•••••••••••••••••••••••••••••••')
      expect(wrapper.html()).contains('icon="bi bi-eye"')
      expect(wrapper.html()).contains('look="no-text"')
      expect(wrapper.html()).contains(
        'icon="bi bi-clipboard-plus" disabled="false" isloading="false" text="pages.share_pictures.button_copy" tooltip="" look="button--white background-white"'
      )
    })
  })
})

describe('Methods', () => {
  describe('toggleToken', () => {
    describe('When one token is already fetched', () => {
      it('should render the token showed', async () => {
        const wrapper = shallowMount(MySettingsView, {
          global: {
            plugins: [i18n],
            mocks: {
              $t: (msg) => msg
            },
            components: {
              Button
            }
          }
        })
        wrapper.vm.userTokens = [
          {
            ...mockResponseTokens[0],
            token: { jwt_token: 'jwtTokenValue' },
            isHidden: true
          }
        ]
        await wrapper.vm.$nextTick()
        const spy = vi.spyOn(wrapper.vm, 'toggleToken')
        const buttonWrapper = wrapper.findComponent(
          '[data-test="button-eye-0"]'
        )
        await buttonWrapper.vm.$emit('trigger')
        expect(spy).toHaveBeenCalledWith(0)
        expect(wrapper.html()).contains('jwtTokenValue')
        expect(wrapper.html()).contains('icon="bi bi-eye-slash"')
      })
    })
    describe('When one token is not fetched yet', async () => {
      it('should render the token showed', async () => {
        axios.get.mockResolvedValue({ data: mockResponseTokens })
        const wrapper = shallowMount(MySettingsView, {
          global: {
            plugins: [i18n],
            mocks: {
              $t: (msg) => msg
            },
            components: {
              Button
            }
          }
        })
        await flushPromises()
        axios.get.mockResolvedValue({ data: { jwt_token: 'my token' } })

        const spy = vi.spyOn(wrapper.vm, 'toggleToken')
        const buttonWrapper = wrapper.findComponent(
          '[data-test="button-eye-0"]'
        )
        await buttonWrapper.vm.$emit('trigger')
        await flushPromises()

        expect(spy).toHaveBeenCalledWith(0)
        expect(wrapper.vm.userTokens[0].isHidden).toBe(false)
        expect(wrapper.vm.userTokens[0].token.jwt_token).toBe('my token')
        expect(wrapper.html()).contains('icon="bi bi-eye-slash"')
      })
    })
  })
  describe('copyText', () => {
    it('calls copyText function on button click', async () => {
      vi.spyOn(axios, 'get').mockResolvedValue({ data: mockResponseTokens })
      vi.mock('../../../utils/copyToClipboard')
      beforeEach(() => {
        vi.useFakeTimers()
      })
      afterEach(() => {
        vi.restoreAllMocks()
      })
      const wrapper = shallowMount(MySettingsView, {
        global: {
          plugins: [i18n],
          mocks: {
            $t: (msg) => msg
          },
          components: {
            Button
          }
        }
      })
      await flushPromises()

      const updateClipboardMock = vi.spyOn(
        copyToClipboardModule,
        'updateClipboard'
      )
      updateClipboardMock.mockReturnValue(true)
      const spy = vi.spyOn(wrapper.vm, 'copyText')
      const buttonWrapper = wrapper.findComponent('[data-test="button-copy-0"]')
      const tokenToCopy = 'token to copy'

      await buttonWrapper.vm.$emit('trigger')
      await updateClipboard(tokenToCopy)
      await flushPromises()

      expect(spy).toHaveBeenCalledWith(0)
      expect(updateClipboard).toHaveBeenCalledWith(tokenToCopy)
      expect(wrapper.vm.userTokens[0].copied).toBe(true)
      expect(wrapper.html()).contains('icon="bi bi-clipboard-check-fill"')
    })
  })
})
