import { TestBed } from '@angular/core/testing';
import { LayoutStateService } from './layout-state.service';

describe('LayoutStateService', () => {
  beforeEach(() => {
    localStorage.clear();
    document.documentElement.classList.remove('dark');
    TestBed.resetTestingModule();
  });

  describe('sidebar state', () => {
    it('defaults to expanded when no preference is persisted', () => {
      const service = TestBed.inject(LayoutStateService);
      expect(service.sidebarCollapsed()).toBe(false);
    });

    it('initialises from the persisted preference', () => {
      localStorage.setItem('portal-shell:sidebar-collapsed', '1');
      const service = TestBed.inject(LayoutStateService);
      expect(service.sidebarCollapsed()).toBe(true);
    });

    it('toggleSidebar flips the value and persists it', () => {
      const service = TestBed.inject(LayoutStateService);
      expect(service.sidebarCollapsed()).toBe(false);

      service.toggleSidebar();
      expect(service.sidebarCollapsed()).toBe(true);
      TestBed.tick();
      expect(localStorage.getItem('portal-shell:sidebar-collapsed')).toBe('1');

      service.toggleSidebar();
      expect(service.sidebarCollapsed()).toBe(false);
      TestBed.tick();
      expect(localStorage.getItem('portal-shell:sidebar-collapsed')).toBe('0');
    });

    it('setSidebarCollapsed writes the explicit value', () => {
      const service = TestBed.inject(LayoutStateService);
      service.setSidebarCollapsed(true);
      expect(service.sidebarCollapsed()).toBe(true);
      TestBed.tick();
      expect(localStorage.getItem('portal-shell:sidebar-collapsed')).toBe('1');
    });
  });

  describe('theme state', () => {
    it('defaults to auto when no preference is persisted', () => {
      const service = TestBed.inject(LayoutStateService);
      expect(service.themeMode()).toBe('auto');
    });

    it('initialises from the persisted theme mode', () => {
      localStorage.setItem('portal-shell:theme-mode', 'dark');
      const service = TestBed.inject(LayoutStateService);
      expect(service.themeMode()).toBe('dark');
    });

    it('ignores an invalid persisted value and falls back to auto', () => {
      localStorage.setItem('portal-shell:theme-mode', 'sepia' as unknown as string);
      const service = TestBed.inject(LayoutStateService);
      expect(service.themeMode()).toBe('auto');
    });

    it('setThemeMode persists the choice and toggles the .dark class on <html>', () => {
      const service = TestBed.inject(LayoutStateService);
      const html = document.documentElement;

      service.setThemeMode('dark');
      TestBed.tick();
      expect(localStorage.getItem('portal-shell:theme-mode')).toBe('dark');
      expect(html.classList.contains('dark')).toBe(true);
      expect(service.effectiveTheme()).toBe('dark');

      service.setThemeMode('light');
      TestBed.tick();
      expect(localStorage.getItem('portal-shell:theme-mode')).toBe('light');
      expect(html.classList.contains('dark')).toBe(false);
      expect(service.effectiveTheme()).toBe('light');
    });

    it('resolves auto via the system preference (jsdom defaults to light)', () => {
      const service = TestBed.inject(LayoutStateService);
      service.setThemeMode('auto');
      TestBed.tick();
      expect(service.themeMode()).toBe('auto');
      // jsdom's matchMedia reports no `prefers-color-scheme: dark` match,
      // so 'auto' resolves to light. We assert the resolution path —
      // not the literal value of the system preference.
      expect(service.effectiveTheme()).toBe('light');
      expect(document.documentElement.classList.contains('dark')).toBe(false);
    });
  });
});
