import { describe, expect, it } from 'vite-plus/test'
import { DialogBoxStub } from '@/__tests__/stubs'
import { userStore } from '@/stores/userStore'
import { screen } from '@testing-library/vue'
import factory from '@/__tests__/factory'
import { invitationService } from '@/services/invitationService'
import { createHarness } from '@/__tests__/TestHarness'
import Component from './UserContextMenu.vue'

describe('userContextMenu.vue', () => {
  const h = createHarness()

  const renderComponent = async (user?: User) => {
    user = user || h.factory('user').make()

    const rendered = h.render(Component, {
      props: {
        user,
      },
    })

    return {
      ...rendered,
      user,
    }
  }

  it('deletes user if confirmed', async () => {
    h.mock(DialogBoxStub.value, 'confirm').mockResolvedValue(true)
    const { user } = await renderComponent(h.factory('user').make({ permissions: { edit: true, delete: true } }))
    const destroyMock = h.mock(userStore, 'destroy')

    await h.user.click(screen.getByText('Delete'))

    expect(destroyMock).toHaveBeenCalledWith(user)
  })

  it('does not delete user if not confirmed', async () => {
    h.mock(DialogBoxStub.value, 'confirm').mockResolvedValue(false)
    await renderComponent(h.factory('user').make({ permissions: { edit: true, delete: true } }))
    const destroyMock = h.mock(userStore, 'destroy')

    await h.user.click(screen.getByText('Delete'))

    expect(destroyMock).not.toHaveBeenCalled()
  })

  it('revokes invite for prospects', async () => {
    h.mock(DialogBoxStub.value, 'confirm').mockResolvedValue(true)
    const prospect = factory('user')
      .state('prospect')
      .make({ permissions: { edit: false, delete: true } })
    await renderComponent(prospect)
    const revokeMock = h.mock(invitationService, 'revoke')

    await h.user.click(screen.getByText('Revoke Invitation'))

    expect(revokeMock).toHaveBeenCalledWith(prospect)
  })

  it('does not revoke invite for prospects if not confirmed', async () => {
    h.mock(DialogBoxStub.value, 'confirm').mockResolvedValue(false)
    await renderComponent(
      factory('user')
        .state('prospect')
        .make({ permissions: { edit: false, delete: true } }),
    )
    await h.user.click(screen.getByText('Revoke Invitation'))
    const revokeMock = h.mock(invitationService, 'revoke')

    await h.user.click(screen.getByText('Revoke Invitation'))

    expect(revokeMock).not.toHaveBeenCalled()
  })

  it('respects the permissions', async () => {
    await renderComponent(h.factory('user').make({ permissions: { edit: false, delete: false } }))
    expect(screen.queryByText('Edit')).toBeNull()
    expect(screen.queryByText('Delete')).toBeNull()
  })
})
