/**
 * Example test demonstrating proper DOM assertion usage.
 * This shows the correct way to compare DOM elements.
 */

import { assert, fixture, html } from '@open-wc/testing'

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

describe('DOM Assertion Examples', () => {
  describe('Basic DOM Element Comparisons', () => {
    it('should compare DOM elements correctly with assert.dom.equal', async () => {
      // Create a test element
      const element = await fixture(html`<div id="test">Content</div>`)

      // Find the same element using querySelector
      const foundElement = document.querySelector('#test')

      // ✅ CORRECT: Use assert.dom.equal for DOM element comparison
      assert.dom.equal(foundElement, element)

      // ❌ WRONG: Never use assert.equal for DOM elements
      // assert.equal(foundElement, element) // This won't work properly
    })

    it('should verify different elements are not equal', async () => {
      const element1 = await fixture(html`<div id="test1">Content 1</div>`)
      const element2 = await fixture(html`<div id="test2">Content 2</div>`)

      // ✅ CORRECT: Use assert.dom.notEqual for different DOM elements
      assert.dom.notEqual(element1, element2)
    })

    it('should compare element snapshots', async () => {
      const element = await fixture(html`<div class="test">Hello World</div>`)

      // ✅ CORRECT: Use assert.dom.equalSnapshot for HTML content comparison
      // Note: equalSnapshot typically takes just the element and compares against saved snapshots
      assert.dom.equalSnapshot(element)
    })

    it('should verify element does not match snapshot', async () => {
      // For this demo, we'll just verify the element exists and has expected content
      const element = await fixture(html`<div class="test">Changed Content</div>`)

      // Verify content directly instead of using snapshots in this example
      assert.equal(element.textContent, 'Changed Content')
      assert.equal(element.className, 'test')
    })
  })

  describe('Advanced DOM Assertion Scenarios', () => {
    it('should wait for element and compare correctly', async () => {
      // Add element after a delay
      setTimeout(() => {
        const element = document.createElement('div')
        element.id = 'delayed-element'
        element.textContent = 'I appeared later'
        document.body.appendChild(element)
      }, 50)

      // Wait for the element to appear
      const foundElement = await window.testUtils.waitForElement('#delayed-element')

      // Get the same element using querySelector
      const queryElement = document.querySelector('#delayed-element')

      // ✅ CORRECT: Compare the DOM elements
      assert.dom.equal(foundElement, queryElement)

      // Also verify the content
      assert.equal(foundElement.textContent, 'I appeared later')
    })

    it('should handle element creation and comparison in tests', async () => {
      // Create element using fixture
      const fixtureElement = await fixture(html`
        <div class="container">
          <span class="child">Child content</span>
        </div>
      `) // Find child element
      const childElement = fixtureElement.querySelector('.child')
      const foundChild = document.querySelector('.child')

      // Verify child element exists
      assert.exists(childElement)
      assert.exists(foundChild)

      // ✅ CORRECT: Compare the child elements
      assert.dom.equal(childElement, foundChild)

      // Verify the parent-child relationship
      assert.dom.equal(childElement!.parentElement, fixtureElement)
    })

    it('should demonstrate element mutation and comparison', async () => {
      const element = await fixture(html`<div class="original">Original</div>`)

      // Verify initial state
      assert.equal(element.textContent, 'Original')
      assert.equal(element.className, 'original')

      // Mutate the element
      element.textContent = 'Modified'
      element.className = 'modified'

      // Verify the changes
      assert.equal(element.textContent, 'Modified')
      assert.equal(element.className, 'modified')
    })

    it('should handle custom elements and DOM assertions', async () => {
      // Define a simple custom element for testing
      if (!customElements.get('test-element')) {
        customElements.define(
          'test-element',
          class extends HTMLElement {
            connectedCallback() {
              this.innerHTML = '<span>Custom element content</span>'
            }
          }
        )
      }

      const customElement = await fixture(html`<test-element></test-element>`)
      const foundCustomElement = document.querySelector('test-element')

      // ✅ CORRECT: Compare custom elements
      assert.dom.equal(customElement, foundCustomElement)

      // Verify the custom element rendered correctly
      const span = customElement.querySelector('span')
      assert.exists(span)
      assert.equal(span.textContent, 'Custom element content')
    })
  })

  describe('Common DOM Assertion Patterns', () => {
    it('should verify element exists before comparing', async () => {
      const element = await fixture(html`<div id="exists">I exist</div>`)

      // First verify the element exists
      assert.exists(element)

      // Then find it and compare
      const foundElement = document.getElementById('exists')
      assert.exists(foundElement)

      // ✅ CORRECT: Now compare the elements
      assert.dom.equal(element, foundElement)
    })

    it('should handle null elements gracefully', () => {
      const nonExistentElement = document.querySelector('#does-not-exist')

      // Verify it's null
      assert.isNull(nonExistentElement)

      // Don't try to use assert.dom.equal with null elements
      // This would throw an error:
      // assert.dom.equal(nonExistentElement, someOtherElement)
    })

    it('should compare elements after DOM manipulation', async () => {
      const container = await fixture(html`<div class="container"></div>`)

      // Add a child element
      const child = document.createElement('span')
      child.textContent = 'Added child'
      container.appendChild(child)

      // Find the child through different methods
      const foundChild1 = container.querySelector('span')
      const foundChild2 = container.firstElementChild

      // ✅ CORRECT: Both should reference the same element
      assert.dom.equal(foundChild1, foundChild2)
      assert.dom.equal(foundChild1, child)
    })
  })
})
