/* eslint-disable @typescript-eslint/no-explicit-any */
// Originally these tests were written for a browser environment.
// They are now adapted to run in a Node.js environment with polyfills for browser APIs.

// @ts-expect-error This is for testing.
globalThis.window = globalThis

// Polyfill for DOM EventTarget APIs in Node.js environment for testing
if (typeof globalThis.Event === 'undefined') {
  class EventPolyfill {
    type: string
    bubbles: boolean
    cancelable: boolean
    composed: boolean
    defaultPrevented = false
    readonly timeStamp: number = Date.now()
    // Stub other properties/methods as needed by the code under test
    target: any | null = null // Using 'any' for simplicity in polyfill
    currentTarget: any | null = null

    constructor(type: string, eventInitDict?: EventInit) {
      this.type = type
      this.bubbles = eventInitDict?.bubbles ?? false
      this.cancelable = eventInitDict?.cancelable ?? false
      this.composed = eventInitDict?.composed ?? false
    }

    preventDefault(): void {
      if (this.cancelable) {
        this.defaultPrevented = true
      }
    }

    stopPropagation(): void {
      /* Stub */
    }
    stopImmediatePropagation(): void {
      /* Stub */
    }
  }
  ;(globalThis as any).Event = EventPolyfill
}

if (typeof globalThis.CustomEvent === 'undefined') {
  class CustomEventPolyfill<T = any> extends (globalThis as any).Event {
    detail: T

    constructor(type: string, eventInitDict?: CustomEventInit<T>) {
      super(type, eventInitDict)
      this.detail = eventInitDict?.detail ?? (null as T)
    }
  }
  ;(globalThis as any).CustomEvent = CustomEventPolyfill
}

if (typeof globalThis.addEventListener !== 'function') {
  const eventListeners = new Map<string, Set<EventListenerOrEventListenerObject>>()

  globalThis.addEventListener = (type: string, listener: EventListenerOrEventListenerObject): void => {
    if (!eventListeners.has(type)) {
      eventListeners.set(type, new Set())
    }
    eventListeners.get(type)!.add(listener)
  }

  globalThis.removeEventListener = (type: string, listener: EventListenerOrEventListenerObject): void => {
    eventListeners.get(type)?.delete(listener)
  }

  globalThis.dispatchEvent = (event: Event): boolean => {
    eventListeners.get(event.type)?.forEach((handler) => {
      if (typeof handler === 'function') handler.call(globalThis, event)
      else handler.handleEvent.call(globalThis, event)
    })
    return !event.defaultPrevented
  }
}
