import { describe, it, expect, vi, beforeEach } from 'vitest';

// Mock BroadcastChannel before importing stores
if (typeof global.BroadcastChannel === 'undefined') {
  (global as any).BroadcastChannel = class MockBroadcastChannel {
    postMessage = vi.fn();
    close = vi.fn();
    addEventListener = vi.fn();
    removeEventListener = vi.fn();
    onmessage = null;
  };
}

import { useUIStore } from './ui';

// Mock window.matchMedia
Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: vi.fn().mockImplementation((query) => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: vi.fn(),
    removeListener: vi.fn(),
    addEventListener: vi.fn(),
    removeEventListener: vi.fn(),
    dispatchEvent: vi.fn(),
  })),
});

// Mock crypto.randomUUID
Object.defineProperty(global, 'crypto', {
  value: {
    randomUUID: () => `test-uuid-${Math.random().toString(36).substring(7)}`,
  },
});

describe('UIStore', () => {
  beforeEach(() => {
    // Reset store state
    useUIStore.setState({
      theme: 'system',
      language: 'en',
      sidebarOpen: true,
      notifications: [],
    });
    vi.clearAllMocks();
  });

  describe('Initial State', () => {
    it('should have correct initial state', () => {
      const state = useUIStore.getState();
      expect(state.theme).toBe('system');
      expect(state.language).toBe('en');
      expect(state.sidebarOpen).toBe(true);
      expect(state.notifications).toEqual([]);
    });
  });

  describe('setTheme', () => {
    it('should set theme to light', () => {
      useUIStore.getState().setTheme('light');
      expect(useUIStore.getState().theme).toBe('light');
      expect(document.documentElement.classList.contains('dark')).toBe(false);
    });

    it('should set theme to dark', () => {
      useUIStore.getState().setTheme('dark');
      expect(useUIStore.getState().theme).toBe('dark');
      expect(document.documentElement.classList.contains('dark')).toBe(true);
    });

    it('should set theme to system', () => {
      useUIStore.getState().setTheme('system');
      expect(useUIStore.getState().theme).toBe('system');
    });
  });

  describe('setLanguage', () => {
    it('should set language to en', () => {
      useUIStore.getState().setLanguage('en');
      expect(useUIStore.getState().language).toBe('en');
    });

    it('should set language to fr', () => {
      useUIStore.getState().setLanguage('fr');
      expect(useUIStore.getState().language).toBe('fr');
    });
  });

  describe('setSidebarOpen', () => {
    it('should set sidebar open state', () => {
      useUIStore.getState().setSidebarOpen(false);
      expect(useUIStore.getState().sidebarOpen).toBe(false);

      useUIStore.getState().setSidebarOpen(true);
      expect(useUIStore.getState().sidebarOpen).toBe(true);
    });
  });

  describe('addNotification', () => {
    it('should add a notification', () => {
      useUIStore.getState().addNotification({
        type: 'success',
        message: 'Test notification',
      });

      const notifications = useUIStore.getState().notifications;
      expect(notifications).toHaveLength(1);
      expect(notifications[0].message).toBe('Test notification');
      expect(notifications[0].type).toBe('success');
      expect(notifications[0].id).toBeDefined();
      expect(notifications[0].timestamp).toBeDefined();
    });

    it('should add multiple notifications', () => {
      useUIStore.getState().addNotification({
        type: 'info',
        message: 'First notification',
      });
      useUIStore.getState().addNotification({
        type: 'warning',
        message: 'Second notification',
      });

      const notifications = useUIStore.getState().notifications;
      expect(notifications).toHaveLength(2);
      expect(notifications[0].message).toBe('First notification');
      expect(notifications[1].message).toBe('Second notification');
    });
  });

  describe('removeNotification', () => {
    it('should remove a notification by id', () => {
      useUIStore.getState().addNotification({
        type: 'success',
        message: 'Test notification',
      });

      const notifications = useUIStore.getState().notifications;
      const notificationId = notifications[0].id;

      useUIStore.getState().removeNotification(notificationId);

      expect(useUIStore.getState().notifications).toHaveLength(0);
    });

    it('should not remove notification with wrong id', () => {
      useUIStore.getState().addNotification({
        type: 'success',
        message: 'Test notification',
      });

      useUIStore.getState().removeNotification('wrong-id');

      expect(useUIStore.getState().notifications).toHaveLength(1);
    });
  });

  describe('markNotificationAsRead', () => {
    it('should mark notification as read', () => {
      useUIStore.getState().addNotification({
        type: 'info',
        message: 'Test notification',
      });

      const notifications = useUIStore.getState().notifications;
      const notificationId = notifications[0].id;

      expect(notifications[0].read).toBeUndefined();

      useUIStore.getState().markNotificationAsRead(notificationId);

      const updatedNotifications = useUIStore.getState().notifications;
      expect(updatedNotifications[0].read).toBe(true);
    });

    it('should not mark other notifications as read', () => {
      useUIStore.getState().addNotification({
        type: 'info',
        message: 'First notification',
      });
      useUIStore.getState().addNotification({
        type: 'warning',
        message: 'Second notification',
      });

      const notifications = useUIStore.getState().notifications;
      const firstId = notifications[0].id;

      useUIStore.getState().markNotificationAsRead(firstId);

      const updatedNotifications = useUIStore.getState().notifications;
      expect(updatedNotifications[0].read).toBe(true);
      expect(updatedNotifications[1].read).toBeUndefined();
    });
  });

  describe('clearNotifications', () => {
    it('should clear all notifications', () => {
      useUIStore.getState().addNotification({
        type: 'info',
        message: 'First notification',
      });
      useUIStore.getState().addNotification({
        type: 'warning',
        message: 'Second notification',
      });

      expect(useUIStore.getState().notifications).toHaveLength(2);

      useUIStore.getState().clearNotifications();

      expect(useUIStore.getState().notifications).toHaveLength(0);
    });
  });
});
