import { describe, it, expect, vi, afterEach } from 'vitest';
import { resolveTheme, isThemePref, readStoredTheme, writeStoredTheme, systemPrefersDark, THEME_STORAGE_KEY } from './theme';

describe('resolveTheme', () => {
  it('explicit dark/light win regardless of system', () => {
    expect(resolveTheme('dark', false)).toBe('dark');
    expect(resolveTheme('dark', true)).toBe('dark');
    expect(resolveTheme('light', true)).toBe('light');
    expect(resolveTheme('light', false)).toBe('light');
  });
  it('system follows the OS preference', () => {
    expect(resolveTheme('system', true)).toBe('dark');
    expect(resolveTheme('system', false)).toBe('light');
  });
});

describe('isThemePref', () => {
  it('accepts valid prefs, rejects junk', () => {
    expect(isThemePref('system')).toBe(true);
    expect(isThemePref('light')).toBe(true);
    expect(isThemePref('dark')).toBe(true);
    expect(isThemePref('blue')).toBe(false);
    expect(isThemePref(null)).toBe(false);
    expect(isThemePref(undefined)).toBe(false);
  });
});

describe('readStoredTheme', () => {
  afterEach(() => vi.unstubAllGlobals());
  it('returns the stored pref when valid', () => {
    vi.stubGlobal('localStorage', { getItem: () => 'dark', setItem: () => {} });
    expect(readStoredTheme()).toBe('dark');
  });
  it('falls back to system when missing or invalid', () => {
    vi.stubGlobal('localStorage', { getItem: () => null, setItem: () => {} });
    expect(readStoredTheme()).toBe('system');
    vi.stubGlobal('localStorage', { getItem: () => 'bogus', setItem: () => {} });
    expect(readStoredTheme()).toBe('system');
  });
  it('falls back to system when localStorage throws', () => {
    vi.stubGlobal('localStorage', {
      getItem: () => {
        throw new Error('blocked');
      },
      setItem: () => {},
    });
    expect(readStoredTheme()).toBe('system');
  });
});

describe('writeStoredTheme', () => {
  afterEach(() => vi.unstubAllGlobals());
  it('writes the pref under the storage key', () => {
    const setItem = vi.fn();
    vi.stubGlobal('localStorage', { getItem: () => null, setItem });
    writeStoredTheme('dark');
    expect(setItem).toHaveBeenCalledWith(THEME_STORAGE_KEY, 'dark');
  });
  it('swallows errors when storage throws', () => {
    vi.stubGlobal('localStorage', {
      setItem: () => {
        throw new Error('blocked');
      },
    });
    expect(() => writeStoredTheme('dark')).not.toThrow();
  });
});

describe('systemPrefersDark', () => {
  afterEach(() => vi.unstubAllGlobals());
  it('reflects the OS matchMedia result', () => {
    vi.stubGlobal('window', { matchMedia: () => ({ matches: true }) });
    expect(systemPrefersDark()).toBe(true);
    vi.stubGlobal('window', { matchMedia: () => ({ matches: false }) });
    expect(systemPrefersDark()).toBe(false);
  });
});
