import '@testing-library/jest-dom/vitest';
import { cleanup } from '@testing-library/svelte';
import { afterEach, beforeAll, vi } from 'vitest';
import {
  navigatingStore,
  pageStore,
  resetMockNavigating,
  resetMockPage,
  updatedStore
} from './src/test/mocks/app-stores';

vi.mock('$app/stores', () => ({
  page: { subscribe: pageStore.subscribe },
  navigating: { subscribe: navigatingStore.subscribe },
  updated: updatedStore
}));

vi.mock('canvas-confetti', () => ({
  default: vi.fn()
}));

class MockIntersectionObserver {
  private callback: IntersectionObserverCallback;

  constructor(callback: IntersectionObserverCallback) {
    this.callback = callback;
  }

  observe(target: Element) {
    this.callback(
      [{ isIntersecting: true, target } as IntersectionObserverEntry],
      this as unknown as IntersectionObserver
    );
  }

  unobserve() {}
  disconnect() {}
}

class MockResizeObserver {
  observe() {}
  unobserve() {}
  disconnect() {}
}

beforeAll(() => {
  Object.defineProperty(window, 'matchMedia', {
    writable: true,
    value: vi.fn().mockImplementation((query: string) => ({
      matches: false,
      media: query,
      onchange: null,
      addListener: vi.fn(),
      removeListener: vi.fn(),
      addEventListener: vi.fn(),
      removeEventListener: vi.fn(),
      dispatchEvent: vi.fn()
    }))
  });

  Object.defineProperty(window, 'scrollTo', {
    writable: true,
    value: vi.fn()
  });

  Object.defineProperty(window, 'requestAnimationFrame', {
    writable: true,
    value: vi.fn(() => 0)
  });

  Object.defineProperty(window, 'cancelAnimationFrame', {
    writable: true,
    value: vi.fn()
  });

  Object.defineProperty(globalThis, 'IntersectionObserver', {
    configurable: true,
    writable: true,
    value: MockIntersectionObserver
  });

  Object.defineProperty(globalThis, 'ResizeObserver', {
    configurable: true,
    writable: true,
    value: MockResizeObserver
  });
});

afterEach(() => {
  cleanup();
  resetMockPage();
  resetMockNavigating();
  vi.clearAllMocks();
  document.head.innerHTML = '';
});
