/**
 * Example test file demonstrating the test setup and utilities.
 * This shows how to use the test infrastructure for UI components.
 */

import { assert } from '@open-wc/testing'
import { testFactory, asyncHelpers, customMatchers } from './helpers/TestUtils.js'
import { UiMock } from './helpers/UiMock.js'

// Import the setup to ensure it runs
import './setup.js'

describe('Test Setup Example', () => {
  describe('Basic Test Infrastructure', () => {
    it('should have test utilities available globally', () => {
      assert.exists(window.testUtils)
      assert.isFunction(window.testUtils.waitForElement)
      assert.isFunction(window.testUtils.waitForCondition)
    })

    it('should have custom matchers available', () => {
      assert.exists(customMatchers.toHaveClasses)
      assert.exists(customMatchers.toBeVisible)
      assert.exists(customMatchers.toHaveAttribute)
    })

    it('should have async helpers available', () => {
      assert.exists(asyncHelpers.waitForAll)
      assert.exists(asyncHelpers.waitForAny)
      assert.exists(asyncHelpers.retry)
    })

    it('should have UiMock utilities available', () => {
      assert.exists(UiMock.keyDown)
      assert.exists(UiMock.keyUp)
      assert.exists(UiMock.keyPress)
      assert.exists(UiMock.getMiddleOfElement)
      assert.exists(UiMock.moveMouse)
      assert.exists(UiMock.dragAndDrop)
      assert.exists(UiMock.getFileDragEvent)
    })
  })

  describe('Element Testing Example', () => {
    let element: HTMLElement

    beforeEach(() => {
      // Clean setup is handled by global setup
      element = document.createElement('div')
      element.id = 'test-element'
      element.className = 'test-class'
      element.setAttribute('data-test', 'value')
      document.body.appendChild(element)
    })

    afterEach(() => {
      // Cleanup is handled by global setup
    })

    it('should test element classes using custom matcher', () => {
      const result = customMatchers.toHaveClasses(element, 'test-class')
      assert.isTrue(result.pass)
    })

    it('should test element visibility using custom matcher', () => {
      const result = customMatchers.toBeVisible(element)
      assert.isTrue(result.pass)
    })

    it('should test element attributes using custom matcher', () => {
      const result = customMatchers.toHaveAttribute(element, 'data-test', 'value')
      assert.isTrue(result.pass)
    })

    it('should wait for element to appear', async () => {
      // Remove element temporarily
      element.remove()

      // Add it back after a delay
      setTimeout(() => {
        document.body.appendChild(element)
      }, 10)

      // Wait for it to appear
      const foundElement = await window.testUtils.waitForElement('#test-element')
      assert.dom.equal(foundElement, element)
    })

    it('should wait for condition to be true', async () => {
      let conditionMet = false

      // Set condition to true after delay
      setTimeout(() => {
        conditionMet = true
      }, 100)

      // Wait for condition
      await window.testUtils.waitForCondition(() => conditionMet)
      assert.isTrue(conditionMet)
    })
  })

  describe('Async Helpers Example', () => {
    it('should wait for all conditions', async () => {
      let condition1 = false
      let condition2 = false

      setTimeout(() => {
        condition1 = true
      }, 50)
      setTimeout(() => {
        condition2 = true
      }, 100)

      await asyncHelpers.waitForAll([() => condition1, () => condition2])

      assert.isTrue(condition1)
      assert.isTrue(condition2)
    })

    it('should wait for any condition', async () => {
      let condition1 = false
      let condition2 = false

      setTimeout(() => {
        condition1 = true
      }, 50)
      setTimeout(() => {
        condition2 = true
      }, 100)

      const index = await asyncHelpers.waitForAny([() => condition1, () => condition2])

      assert.equal(index, 0) // First condition should be met first
      assert.isTrue(condition1)
    })

    it('should retry failed operations', async () => {
      let attempts = 0

      const operation = async () => {
        attempts++
        if (attempts < 3) {
          throw new Error('Not ready yet')
        }
        return 'success'
      }

      const result = await asyncHelpers.retry(operation, 5, 10)
      assert.equal(result, 'success')
      assert.equal(attempts, 3)
    })
  })

  describe('Test Factory Example', () => {
    it('should create data factory', () => {
      const userFactory = testFactory.createDataFactory({
        id: 1,
        name: 'Test User',
        email: 'test@example.com',
      })

      const user1 = userFactory()
      assert.equal(user1.name, 'Test User')

      const user2 = userFactory({ name: 'Custom User' })
      assert.equal(user2.name, 'Custom User')
      assert.equal(user2.email, 'test@example.com') // Keeps default
    })
  })

  describe('UI Interaction Example', () => {
    let button: HTMLButtonElement

    beforeEach(() => {
      button = document.createElement('button')
      button.textContent = 'Click me'
      button.style.width = '100px'
      button.style.height = '40px'
      button.style.position = 'absolute'
      button.style.top = '100px'
      button.style.left = '100px'
      document.body.appendChild(button)
    })

    it('should simulate keyboard interaction', async () => {
      let keyPressed = false

      button.addEventListener('keydown', (e) => {
        if (e.code === 'Enter') {
          keyPressed = true
        }
      })

      await UiMock.keyPress(button, 'Enter')
      assert.isTrue(keyPressed)
    })

    it('should get element center position', () => {
      const center = UiMock.getMiddleOfElement(button)
      assert.isNumber(center.x)
      assert.isNumber(center.y)
      assert.isAbove(center.x, 0)
      assert.isAbove(center.y, 0)
    })

    it('should create file drag event', () => {
      const file = new File(['test content'], 'test.txt', { type: 'text/plain' })
      const dragEvent = UiMock.getFileDragEvent('drop', { file })

      assert.equal(dragEvent.type, 'drop')
      assert.exists(dragEvent.dataTransfer)
      assert.equal(dragEvent.dataTransfer!.files.length, 1)
      assert.equal(dragEvent.dataTransfer!.files[0].name, 'test.txt')
    })
  })
})
