/**
 * Jest Test Setup
 * Global test configuration and helpers
 */

// Mock browser APIs that are not available in jsdom
global.requestAnimationFrame = (callback) => {
  return setTimeout(callback, 16);
};

global.cancelAnimationFrame = (id) => {
  clearTimeout(id);
};

// Mock performance API
global.performance = {
  now: () => Date.now(),
  mark: () => {},
  measure: () => {},
  getEntriesByType: () => [],
  getEntriesByName: () => []
};

// Mock IntersectionObserver
global.IntersectionObserver = class IntersectionObserver {
  constructor(callback, options = {}) {
    this.callback = callback;
    this.options = options;
    this.elements = new Set();
  }
  
  observe(element) {
    this.elements.add(element);
  }
  
  unobserve(element) {
    this.elements.delete(element);
  }
  
  disconnect() {
    this.elements.clear();
  }
  
  // Helper for testing
  trigger(entries) {
    this.callback(entries);
  }
};

// Mock ResizeObserver
global.ResizeObserver = class ResizeObserver {
  constructor(callback) {
    this.callback = callback;
    this.elements = new Set();
  }
  
  observe(element) {
    this.elements.add(element);
  }
  
  unobserve(element) {
    this.elements.delete(element);
  }
  
  disconnect() {
    this.elements.clear();
  }
};

// Mock navigator
Object.defineProperty(global.navigator, 'connection', {
  value: {
    effectiveType: '4g'
  },
  writable: true,
  configurable: true
});

// Mock console methods for testing
const originalConsole = { ...console };
global.console = {
  ...console,
  // Keep error/warn for debugging
  error: originalConsole.error,
  warn: originalConsole.warn,
  // Mock log/info to avoid spam
  log: () => {},
  info: () => {}
};

// Global test helpers
global.createMockElement = (tagName = 'div', attributes = {}) => {
  const element = document.createElement(tagName);
  Object.entries(attributes).forEach(([key, value]) => {
    if (key.startsWith('data-')) {
      element.dataset[key.replace('data-', '')] = value;
    } else {
      element.setAttribute(key, value);
    }
  });
  return element;
};

global.waitForAnimationFrame = () => {
  return new Promise(resolve => requestAnimationFrame(resolve));
};

global.waitFor = (ms) => {
  return new Promise(resolve => setTimeout(resolve, ms));
};

// Module test helpers
global.createMockModule = (name, overrides = {}) => {
  // Create mock functions manually (jest.fn() not available here)
  const createMockFn = () => {
    const fn = (...args) => {};
    fn.mock = { calls: [], results: [] };
    return fn;
  };
  
  return {
    init: createMockFn(),
    destroy: createMockFn(),
    definition: {
      name,
      version: '1.0.0',
      dependencies: [],
      provides: [],
      priority: 0
    },
    ...overrides
  };
};

// State test helpers  
global.createMockStateManager = () => {
  const state = new Map();
  const subscribers = new Map();
  
  // Create mock functions manually (jest.fn() not available here)
  const createMockFn = (impl) => {
    const fn = (...args) => impl(...args);
    fn.mock = { calls: [], results: [] };
    return fn;
  };
  
  return {
    register: createMockFn((key, defaultValue) => {
      state.set(key, defaultValue);
      subscribers.set(key, []);
    }),
    get: createMockFn((key) => state.get(key)),
    set: createMockFn((key, value) => {
      const oldValue = state.get(key);
      state.set(key, value);
      // Trigger subscribers
      const subs = subscribers.get(key) || [];
      subs.forEach(callback => callback(value, oldValue, key));
      return true;
    }),
    subscribe: createMockFn((key, callback) => {
      if (!subscribers.has(key)) {
        subscribers.set(key, []);
      }
      subscribers.get(key).push(callback);
      return `sub_${key}_${Date.now()}`;
    }),
    unsubscribe: createMockFn(() => {}),
    cleanup: createMockFn(() => {}),
    reset: createMockFn(() => {
      state.clear();
      subscribers.clear();
    })
  };
};

// Clean up after each test
if (typeof afterEach !== 'undefined') {
  afterEach(() => {
    // Reset DOM
    document.body.innerHTML = '';
    document.head.innerHTML = '';
    
    // Clear all timers
    if (typeof jest !== 'undefined' && jest.clearAllTimers) {
      jest.clearAllTimers();
    }
    
    // Clear all mocks
    if (typeof jest !== 'undefined' && jest.clearAllMocks) {
      jest.clearAllMocks();
    }
  });
}