import { test } from '@japa/runner'
import sinon from 'sinon'
import { EventTypes } from '../../../src/events/EventTypes.js'
import { Events } from '../../../src/events/Events.js'
import { ensureUnique } from './EventsTestHelpers.js'
import './events_polyfills.js'

test.group('Events > Reporting > EventTypes.Reporting', () => {
  test('has the namespace', ({ assert }) => {
    assert.typeOf(EventTypes.Reporting, 'object')
  })

  test('has "{prop}" property')
    .with([{ prop: 'error', value: 'reporterror' }])
    .run(({ assert }, { prop, value }) => {
      // @ts-expect-error Used in testing
      assert.equal(EventTypes.Reporting[prop], value)
    })

  test('has unique events for the namespace', () => {
    ensureUnique('EventTypes.Reporting', EventTypes.Reporting)
  })
})

test.group('Events > Reporting > Events.Reporting > error()', () => {
  const err = new Error('Test Error')
  const desc = 'test error description'
  const cmp = 'test-component'

  test('dispatches the event', ({ assert }) => {
    const spy = sinon.spy()
    globalThis.addEventListener(EventTypes.Reporting.error, spy)
    Events.Reporting.error(desc)
    globalThis.removeEventListener(EventTypes.Reporting.error, spy)
    assert.isTrue(spy.calledOnce)
  })

  test('has the description on the event', ({ assert }) => {
    const spy = sinon.spy()
    globalThis.addEventListener(EventTypes.Reporting.error, spy)
    Events.Reporting.error(desc)
    globalThis.removeEventListener(EventTypes.Reporting.error, spy)
    const e = spy.args[0][0] as CustomEvent
    assert.equal(e.detail.description, desc)
  })

  test('has the error on the event when provided', ({ assert }) => {
    const spy = sinon.spy()
    globalThis.addEventListener(EventTypes.Reporting.error, spy)
    Events.Reporting.error(desc, err)
    globalThis.removeEventListener(EventTypes.Reporting.error, spy)
    const e = spy.args[0][0] as CustomEvent
    assert.deepEqual(e.detail.error, err)
  })

  test('error property is undefined when not provided', ({ assert }) => {
    const spy = sinon.spy()
    globalThis.addEventListener(EventTypes.Reporting.error, spy)
    Events.Reporting.error(desc)
    globalThis.removeEventListener(EventTypes.Reporting.error, spy)
    const e = spy.args[0][0] as CustomEvent
    assert.isUndefined(e.detail.error)
  })

  test('has the component on the event when provided', ({ assert }) => {
    const spy = sinon.spy()
    globalThis.addEventListener(EventTypes.Reporting.error, spy)
    Events.Reporting.error(desc, err, cmp)
    globalThis.removeEventListener(EventTypes.Reporting.error, spy)
    const e = spy.args[0][0] as CustomEvent
    assert.equal(e.detail.component, cmp)
  })

  test('component property is undefined when not provided', ({ assert }) => {
    const spy = sinon.spy()
    globalThis.addEventListener(EventTypes.Reporting.error, spy)
    Events.Reporting.error(desc, err) // No component here
    globalThis.removeEventListener(EventTypes.Reporting.error, spy)
    const e = spy.args[0][0] as CustomEvent
    assert.isUndefined(e.detail.component)
  })
})
