import { vi } from 'vitest';

// Mock localStorage
const localStorageMock = {
  store: {} as Record<string, string>,
  getItem: vi.fn((key: string) => localStorageMock.store[key] || null),
  setItem: vi.fn((key: string, value: string) => {
    localStorageMock.store[key] = value;
  }),
  removeItem: vi.fn((key: string) => {
    delete localStorageMock.store[key];
  }),
  clear: vi.fn(() => {
    localStorageMock.store = {};
  }),
  get length() {
    return Object.keys(localStorageMock.store).length;
  },
  key: vi.fn((index: number) => Object.keys(localStorageMock.store)[index] || null),
};

vi.stubGlobal('localStorage', localStorageMock);

// Mock fetch
vi.stubGlobal(
  'fetch',
  vi.fn(() =>
    Promise.resolve({
      ok: true,
      status: 200,
      json: () => Promise.resolve({}),
      text: () => Promise.resolve(''),
    })
  )
);

// Mock crypto for fingerprinting
const cryptoMock = {
  subtle: {
    digest: vi.fn(async (_algorithm: string, data: ArrayBuffer) => {
      // Simple mock hash - returns predictable data
      const view = new Uint8Array(data);
      const hash = new Uint8Array(32);
      for (let i = 0; i < hash.length; i++) {
        hash[i] = (view[i % view.length] || 0) ^ (i * 7);
      }
      return hash.buffer;
    }),
  },
  getRandomValues: vi.fn(<T extends ArrayBufferView | null>(arr: T): T => {
    if (arr instanceof Uint8Array) {
      for (let i = 0; i < arr.length; i++) {
        arr[i] = Math.floor(Math.random() * 256);
      }
    }
    return arr;
  }),
};

vi.stubGlobal('crypto', cryptoMock);

// Mock document.cookie
let documentCookie = '';
Object.defineProperty(document, 'cookie', {
  get: () => documentCookie,
  set: (value: string) => {
    documentCookie = value;
  },
  configurable: true,
});

// Mock navigator properties
Object.defineProperty(navigator, 'userAgent', {
  value: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
  configurable: true,
});

Object.defineProperty(navigator, 'language', {
  value: 'de-DE',
  configurable: true,
});

Object.defineProperty(navigator, 'platform', {
  value: 'MacIntel',
  configurable: true,
});

Object.defineProperty(navigator, 'doNotTrack', {
  value: null,
  configurable: true,
});

Object.defineProperty(navigator, 'maxTouchPoints', {
  value: 0,
  configurable: true,
});

// Mock screen
Object.defineProperty(window, 'screen', {
  value: {
    width: 1920,
    height: 1080,
    colorDepth: 24,
    pixelDepth: 24,
    availWidth: 1920,
    availHeight: 1040,
    orientation: { type: 'landscape-primary', angle: 0 },
  },
  configurable: true,
});

// Mock location
Object.defineProperty(window, 'location', {
  value: {
    protocol: 'https:',
    hostname: 'localhost',
    port: '3000',
    pathname: '/',
    href: 'https://localhost:3000/',
  },
  writable: true,
  configurable: true,
});

// Reset mocks before each test
beforeEach(() => {
  localStorageMock.store = {};
  localStorageMock.getItem.mockClear();
  localStorageMock.setItem.mockClear();
  localStorageMock.removeItem.mockClear();
  localStorageMock.clear.mockClear();
  documentCookie = '';
  vi.clearAllMocks();
});

// Export for use in tests
export { localStorageMock };
