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

import { useUiStore } from '@/stores/ui'
import LoadingOverlay from './LoadingOverlay.vue'

describe('LoadingOverlay', () => {
  beforeEach(() => {
    setActivePinia(createPinia())
    // Clear any teleported content from previous tests
    document.body.innerHTML = ''
  })

  describe('visibility', () => {
    it('is not visible when not loading', () => {
      /**
       * Test that the overlay is hidden by default.
       *
       * When no loading operations are active, the overlay should
       * not be visible to avoid blocking the UI.
       */
      mount(LoadingOverlay)
      const ui = useUiStore()

      expect(ui.isLoading).toBe(false)
      expect(document.body.querySelector('.fixed')).toBeNull()
    })

    it('is visible when loading', async () => {
      /**
       * Test that the overlay appears when loading starts.
       *
       * The overlay should be teleported to body and be visible
       * when showLoading() is called.
       */
      mount(LoadingOverlay)
      const ui = useUiStore()

      ui.showLoading()

      // Wait for the teleport and transition
      await new Promise(resolve => setTimeout(resolve, 50))

      expect(ui.isLoading).toBe(true)
      expect(document.body.querySelector('.fixed')).not.toBeNull()
    })

    it('shows loading message when provided', async () => {
      /**
       * Test that loading messages are displayed.
       *
       * Components can provide context about what's loading,
       * which should be shown to the user.
       */
      mount(LoadingOverlay)
      const ui = useUiStore()

      ui.showLoading('Saving game...')

      await new Promise(resolve => setTimeout(resolve, 50))

      expect(document.body.textContent).toContain('Saving game...')
    })

    it('hides when loading count reaches zero', async () => {
      /**
       * Test that the overlay hides after all loading calls complete.
       *
       * Multiple components may trigger loading simultaneously.
       * The overlay should stay visible until all are done.
       */
      mount(LoadingOverlay)
      const ui = useUiStore()

      ui.showLoading()
      ui.showLoading() // Second concurrent load

      await new Promise(resolve => setTimeout(resolve, 50))
      expect(document.body.querySelector('.fixed')).not.toBeNull()

      ui.hideLoading() // First load done
      await new Promise(resolve => setTimeout(resolve, 50))
      expect(document.body.querySelector('.fixed')).not.toBeNull() // Still visible

      ui.hideLoading() // Second load done
      await new Promise(resolve => setTimeout(resolve, 250)) // Wait for transition
      expect(document.body.querySelector('.fixed')).toBeNull() // Now hidden
    })
  })
})
