import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'

import LinkedAccountCard from './LinkedAccountCard.vue'
import type { LinkedAccount } from '@/composables/useProfile'

describe('LinkedAccountCard', () => {
  const createAccount = (overrides: Partial<LinkedAccount> = {}): LinkedAccount => ({
    provider: 'google',
    providerUserId: 'g123',
    email: 'test@gmail.com',
    linkedAt: '2026-01-15T10:30:00Z',
    ...overrides,
  })

  describe('rendering', () => {
    it('displays provider name', () => {
      /**
       * Test that the provider name is displayed.
       *
       * Users should be able to identify which OAuth provider
       * each linked account belongs to.
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount({ provider: 'google' }),
          isOnlyAccount: false,
          isUnlinking: false,
        },
      })

      expect(wrapper.text()).toContain('Google')
    })

    it('displays email when available', () => {
      /**
       * Test that the email is displayed for linked accounts.
       *
       * The email helps users identify which specific account
       * is linked (e.g., if they have multiple Google accounts).
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount({ email: 'user@example.com' }),
          isOnlyAccount: false,
          isUnlinking: false,
        },
      })

      expect(wrapper.text()).toContain('user@example.com')
    })

    it('displays fallback text when email is null', () => {
      /**
       * Test fallback display when no email is available.
       *
       * Some providers may not provide email (e.g., Discord).
       * We should show a reasonable fallback.
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount({ provider: 'discord', email: null }),
          isOnlyAccount: false,
          isUnlinking: false,
        },
      })

      expect(wrapper.text()).toContain('Discord Account')
    })

    it('displays linked date formatted', () => {
      /**
       * Test that the linked date is displayed in a readable format.
       *
       * Users should know when they linked each account for security.
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount({ linkedAt: '2026-01-15T10:30:00Z' }),
          isOnlyAccount: false,
          isUnlinking: false,
        },
      })

      // Should contain "Linked" and some date text
      expect(wrapper.text()).toContain('Linked')
      expect(wrapper.text()).toMatch(/Jan|15|2026/)
    })

    it('shows correct icon for Google', () => {
      /**
       * Test Google provider icon.
       *
       * Visual differentiation helps users quickly identify providers.
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount({ provider: 'google' }),
          isOnlyAccount: false,
          isUnlinking: false,
        },
      })

      expect(wrapper.text()).toContain('🔵')
    })

    it('shows correct icon for Discord', () => {
      /**
       * Test Discord provider icon.
       *
       * Visual differentiation helps users quickly identify providers.
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount({ provider: 'discord' }),
          isOnlyAccount: false,
          isUnlinking: false,
        },
      })

      expect(wrapper.text()).toContain('🟣')
    })
  })

  describe('unlink button', () => {
    it('is enabled when not the only account', () => {
      /**
       * Test that unlink is enabled with multiple accounts.
       *
       * Users should be able to unlink accounts as long as
       * they have at least one other linked account.
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount(),
          isOnlyAccount: false,
          isUnlinking: false,
        },
      })

      const button = wrapper.find('button')
      expect(button.attributes('disabled')).toBeUndefined()
    })

    it('is disabled when only account', () => {
      /**
       * Test that unlink is disabled for the only account.
       *
       * Users cannot unlink their only OAuth provider because
       * they would be locked out of their account.
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount(),
          isOnlyAccount: true,
          isUnlinking: false,
        },
      })

      const button = wrapper.find('button')
      expect(button.attributes('disabled')).toBeDefined()
    })

    it('is disabled while unlinking', () => {
      /**
       * Test that unlink is disabled during operation.
       *
       * Prevent double-clicks and show feedback while
       * the unlink operation is in progress.
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount(),
          isOnlyAccount: false,
          isUnlinking: true,
        },
      })

      const button = wrapper.find('button')
      expect(button.attributes('disabled')).toBeDefined()
      expect(button.text()).toContain('Unlinking')
    })

    it('shows tooltip explaining why unlink is disabled', () => {
      /**
       * Test tooltip for disabled unlink button.
       *
       * Users should understand why they can't unlink
       * their only account.
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount(),
          isOnlyAccount: true,
          isUnlinking: false,
        },
      })

      const button = wrapper.find('button')
      expect(button.attributes('title')).toContain('Cannot unlink')
    })

    it('emits unlink event with provider when clicked', async () => {
      /**
       * Test unlink event emission.
       *
       * When the user clicks unlink, the component should emit
       * an event with the provider name for the parent to handle.
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount({ provider: 'discord' }),
          isOnlyAccount: false,
          isUnlinking: false,
        },
      })

      await wrapper.find('button').trigger('click')

      expect(wrapper.emitted('unlink')).toBeTruthy()
      expect(wrapper.emitted('unlink')![0]).toEqual(['discord'])
    })

    it('does not emit when only account', async () => {
      /**
       * Test that unlink is not emitted for only account.
       *
       * Even if the button is somehow clicked, the event
       * should not be emitted.
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount(),
          isOnlyAccount: true,
          isUnlinking: false,
        },
      })

      await wrapper.find('button').trigger('click')

      expect(wrapper.emitted('unlink')).toBeFalsy()
    })

    it('does not emit while unlinking', async () => {
      /**
       * Test that unlink is not emitted while in progress.
       *
       * Prevent duplicate requests if button is clicked
       * while an operation is already in progress.
       */
      const wrapper = mount(LinkedAccountCard, {
        props: {
          account: createAccount(),
          isOnlyAccount: false,
          isUnlinking: true,
        },
      })

      await wrapper.find('button').trigger('click')

      expect(wrapper.emitted('unlink')).toBeFalsy()
    })
  })
})
