import { afterEach, describe, expect, it, vi } from 'vitest';
import { HAPTICS_STORAGE_KEY, getHapticsPreference, isHapticsEnabled, setHapticsPreference, supportsHaptics, triggerHaptic } from '../haptics';

describe('haptics', () => {
  afterEach(() => {
    window.localStorage.removeItem(HAPTICS_STORAGE_KEY);
  });

  it('returns false when vibrate is unavailable', () => {
    const original = navigator.vibrate;
    Object.defineProperty(navigator, 'vibrate', { configurable: true, value: undefined });
    expect(supportsHaptics()).toBe(false);
    Object.defineProperty(navigator, 'vibrate', { configurable: true, value: original });
  });

  it('returns stored preference when set', () => {
    window.localStorage.removeItem(HAPTICS_STORAGE_KEY);
    expect(getHapticsPreference()).toBe(true);
    setHapticsPreference(false);
    expect(getHapticsPreference()).toBe(false);
  });

  it('reports disabled when reduced motion is enabled', () => {
    const originalMatchMedia = window.matchMedia;
    const vibrate = vi.fn();

    Object.defineProperty(window, 'matchMedia', {
      configurable: true,
      value: vi.fn().mockReturnValue({ matches: true }),
    });
    Object.defineProperty(navigator, 'vibrate', { configurable: true, value: vibrate });
    setHapticsPreference(true);

    expect(isHapticsEnabled()).toBe(false);

    Object.defineProperty(window, 'matchMedia', {
      configurable: true,
      value: originalMatchMedia,
    });
  });

  it('triggers vibration only when enabled', () => {
    const originalMatchMedia = window.matchMedia;
    const vibrate = vi.fn();

    Object.defineProperty(window, 'matchMedia', {
      configurable: true,
      value: vi.fn().mockReturnValue({ matches: false }),
    });
    Object.defineProperty(navigator, 'vibrate', { configurable: true, value: vibrate });

    triggerHaptic('selection');
    expect(vibrate).toHaveBeenCalled();
    setHapticsPreference(false);
    triggerHaptic('selection');
    expect(vibrate).toHaveBeenCalledTimes(1);

    Object.defineProperty(window, 'matchMedia', {
      configurable: true,
      value: originalMatchMedia,
    });
  });
});
