import '@testing-library/jest-dom';

declare const global: typeof globalThis;

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

// Mock IntersectionObserver
class MockIntersectionObserver {
  observe = jest.fn();
  disconnect = jest.fn();
  unobserve = jest.fn();
}

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

// Mock ResizeObserver
class MockResizeObserver {
  observe = jest.fn();
  disconnect = jest.fn();
  unobserve = jest.fn();
}

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

// Mock crypto.subtle
Object.defineProperty(global, 'crypto', {
  writable: true,
  value: {
    subtle: {
      importKey: jest.fn(),
      sign: jest.fn(),
      verify: jest.fn(),
      digest: jest.fn(),
      encrypt: jest.fn(),
      decrypt: jest.fn(),
      generateKey: jest.fn(),
      deriveKey: jest.fn(),
      deriveBits: jest.fn(),
      wrapKey: jest.fn(),
      unwrapKey: jest.fn(),
    },
    getRandomValues: jest.fn((array: Uint8Array) => array),
    randomUUID: jest.fn(() => 'mock-uuid'),
  } as unknown as Crypto,
});

// Mock TextEncoder/TextDecoder
Object.defineProperty(global, 'TextEncoder', {
  writable: true,
  value: class {
    encode(text: string): Uint8Array {
      const arr = new Uint8Array(text.length);
      for (let i = 0; i < text.length; i++) {
        arr[i] = text.charCodeAt(i);
      }
      return arr;
    }
  } as unknown as typeof TextEncoder,
});

Object.defineProperty(global, 'TextDecoder', {
  writable: true,
  value: class {
    decode(buffer: Uint8Array): string {
      let str = '';
      for (let i = 0; i < buffer.length; i++) {
        str += String.fromCharCode(buffer[i]);
      }
      return str;
    }
  } as unknown as typeof TextDecoder,
});

// Suppress console errors during tests
Object.defineProperty(global, 'console', {
  writable: true,
  value: {
    ...console,
    error: jest.fn(),
    warn: jest.fn(),
  },
});
