import '@testing-library/jest-dom/vitest'
import { afterAll, afterEach, beforeAll } from 'vitest'
import { cleanup } from '@testing-library/react'
import { server } from './msw/server'
import { setToken, setNavigateToLogin } from '../src/api'
import { __resetBootstrapInflightForTests } from '../src/auth'
import { resetAdminSettingsSeed } from './msw/handlers/admin-settings'

// JSDOM polyfills for browser APIs production code touches at mount time.
// These are no-op stubs — tests that exercise the actual behavior install
// richer fakes per-suite (e.g. `tests/sse_lifecycle.test.tsx` overrides
// `globalThis.EventSource` and restores it; that pattern still works).
class NoopResizeObserver {
  observe(): void {}
  unobserve(): void {}
  disconnect(): void {}
}

class NoopEventSource extends EventTarget {
  url: string
  readyState: 0 | 1 | 2 = 0
  onopen: ((e: Event) => void) | null = null
  onmessage: ((e: MessageEvent) => void) | null = null
  onerror: ((e: Event) => void) | null = null
  constructor(url: string | URL) {
    super()
    this.url = String(url)
  }
  close(): void {
    this.readyState = 2
  }
  static readonly CONNECTING = 0
  static readonly OPEN = 1
  static readonly CLOSED = 2
}

const g = globalThis as unknown as {
  ResizeObserver?: typeof NoopResizeObserver
  EventSource?: typeof NoopEventSource
}
if (!g.ResizeObserver) g.ResizeObserver = NoopResizeObserver
if (!g.EventSource) g.EventSource = NoopEventSource

// MSW boundary configured per AZ-456 AC-3:
//   - All outbound /api/<service>/... fetches MUST be intercepted.
//   - A test missing a handler for a network request is a HARD failure
//     (onUnhandledRequest: 'error'). This is how AC-3 is enforced for
//     fast-profile tests; a leaked external request would otherwise
//     escape the test environment silently.
beforeAll(() => {
  server.listen({ onUnhandledRequest: 'error' })
})

afterEach(() => {
  cleanup()
  server.resetHandlers()
  setToken(null)
  setNavigateToLogin(() => {
    /* default no-op for tests; production accessor restored implicitly
       on next module reload — tests must re-seed if they assert on it. */
  })
  // AZ-510 — clear AuthProvider's module-scoped in-flight bootstrap promise so
  // a never-resolving fixture in test N does not leak into test N+1.
  __resetBootstrapInflightForTests()
  // v2 admin settings — module-scoped seed mutates on PATCH; reset between tests.
  resetAdminSettingsSeed()
})

afterAll(() => {
  server.close()
})
