/**
 * Tests for calendarStore — Phase 7 Task 7.7
 *
 * Tests: Initial state, view mode, navigation (month/week/day),
 * activeCalendarId, calendars, selectedEntry, toggleCalendarVisibility
 */
import { describe, it, expect, beforeEach } from 'vitest';
import { useCalendarStore } from '../calendarStore';

describe('calendarStore', () => {
  beforeEach(() => {
    // Reset to known state
    const today = new Date();
    useCalendarStore.setState({
      visibleMonth: new Date(today.getFullYear(), today.getMonth(), 1),
      visibleWeek: new Date(today),
      visibleDay: new Date(today),
      rangeStart: new Date(today),
      rangeEnd: new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30),
      viewMode: 'month',
      activeCalendarId: null,
      calendars: [],
      selectedEntry: null,
      visibleCalendarIds: new Set<string>(),
    });
  });

  describe('initial state', () => {
    it('starts with month view mode', () => {
      expect(useCalendarStore.getState().viewMode).toBe('month');
    });

    it('starts with null activeCalendarId', () => {
      expect(useCalendarStore.getState().activeCalendarId).toBeNull();
    });

    it('starts with empty calendars', () => {
      expect(useCalendarStore.getState().calendars).toEqual([]);
    });

    it('starts with null selectedEntry', () => {
      expect(useCalendarStore.getState().selectedEntry).toBeNull();
    });

    it('starts with empty visibleCalendarIds', () => {
      expect(useCalendarStore.getState().visibleCalendarIds.size).toBe(0);
    });
  });

  describe('setViewMode', () => {
    it('sets view mode to day', () => {
      useCalendarStore.getState().setViewMode('day');
      expect(useCalendarStore.getState().viewMode).toBe('day');
    });

    it('sets view mode to week', () => {
      useCalendarStore.getState().setViewMode('week');
      expect(useCalendarStore.getState().viewMode).toBe('week');
    });

    it('sets view mode to range', () => {
      useCalendarStore.getState().setViewMode('range');
      expect(useCalendarStore.getState().viewMode).toBe('range');
    });
  });

  describe('goToNextMonth', () => {
    it('advances visible month by 1', () => {
      const initial = new Date(2024, 5, 1); // June 2024
      useCalendarStore.getState().setVisibleMonth(initial);
      useCalendarStore.getState().goToNextMonth();
      expect(useCalendarStore.getState().visibleMonth.getMonth()).toBe(6); // July
      expect(useCalendarStore.getState().visibleMonth.getFullYear()).toBe(2024);
    });

    it('wraps to next year when in December', () => {
      const initial = new Date(2024, 11, 1); // December 2024
      useCalendarStore.getState().setVisibleMonth(initial);
      useCalendarStore.getState().goToNextMonth();
      expect(useCalendarStore.getState().visibleMonth.getMonth()).toBe(0); // January
      expect(useCalendarStore.getState().visibleMonth.getFullYear()).toBe(2025);
    });
  });

  describe('goToPrevMonth', () => {
    it('decreases visible month by 1', () => {
      const initial = new Date(2024, 5, 1); // June 2024
      useCalendarStore.getState().setVisibleMonth(initial);
      useCalendarStore.getState().goToPrevMonth();
      expect(useCalendarStore.getState().visibleMonth.getMonth()).toBe(4); // May
    });

    it('wraps to previous year when in January', () => {
      const initial = new Date(2024, 0, 1); // January 2024
      useCalendarStore.getState().setVisibleMonth(initial);
      useCalendarStore.getState().goToPrevMonth();
      expect(useCalendarStore.getState().visibleMonth.getMonth()).toBe(11); // December
      expect(useCalendarStore.getState().visibleMonth.getFullYear()).toBe(2023);
    });
  });

  describe('goToNextWeek', () => {
    it('advances visible week by 7 days', () => {
      const initial = new Date(2024, 5, 10); // June 10, 2024
      useCalendarStore.getState().setVisibleWeek(initial);
      useCalendarStore.getState().goToNextWeek();
      expect(useCalendarStore.getState().visibleWeek.getDate()).toBe(17);
    });
  });

  describe('goToPrevWeek', () => {
    it('decreases visible week by 7 days', () => {
      const initial = new Date(2024, 5, 17); // June 17, 2024
      useCalendarStore.getState().setVisibleWeek(initial);
      useCalendarStore.getState().goToPrevWeek();
      expect(useCalendarStore.getState().visibleWeek.getDate()).toBe(10);
    });
  });

  describe('goToNextDay', () => {
    it('advances visible day by 1', () => {
      const initial = new Date(2024, 5, 15);
      useCalendarStore.getState().setVisibleDay(initial);
      useCalendarStore.getState().goToNextDay();
      expect(useCalendarStore.getState().visibleDay.getDate()).toBe(16);
    });
  });

  describe('goToPrevDay', () => {
    it('decreases visible day by 1', () => {
      const initial = new Date(2024, 5, 15);
      useCalendarStore.getState().setVisibleDay(initial);
      useCalendarStore.getState().goToPrevDay();
      expect(useCalendarStore.getState().visibleDay.getDate()).toBe(14);
    });
  });

  describe('goToToday', () => {
    it('sets visibleMonth to current month start', () => {
      useCalendarStore.getState().setVisibleMonth(new Date(2020, 0, 1));
      useCalendarStore.getState().goToToday();
      const today = new Date();
      expect(useCalendarStore.getState().visibleMonth.getMonth()).toBe(today.getMonth());
      expect(useCalendarStore.getState().visibleMonth.getFullYear()).toBe(today.getFullYear());
    });

    it('sets visibleDay to today', () => {
      useCalendarStore.getState().setVisibleDay(new Date(2020, 0, 1));
      useCalendarStore.getState().goToToday();
      const today = new Date();
      expect(useCalendarStore.getState().visibleDay.getDate()).toBe(today.getDate());
    });
  });

  describe('setActiveCalendarId', () => {
    it('sets active calendar id', () => {
      useCalendarStore.getState().setActiveCalendarId('cal-1');
      expect(useCalendarStore.getState().activeCalendarId).toBe('cal-1');
    });

    it('sets active calendar id to null', () => {
      useCalendarStore.getState().setActiveCalendarId('cal-1');
      useCalendarStore.getState().setActiveCalendarId(null);
      expect(useCalendarStore.getState().activeCalendarId).toBeNull();
    });
  });

  describe('setCalendars', () => {
    it('sets calendars list', () => {
      const mockCalendars = [
        { id: 'cal-1', name: 'Calendar 1', color: '#ff0000', tenant_id: 't1', owner_id: 'u1', is_active: true, created_at: '', updated_at: '' },
      ] as any;
      useCalendarStore.getState().setCalendars(mockCalendars);
      expect(useCalendarStore.getState().calendars).toHaveLength(1);
    });
  });

  describe('setSelectedEntry', () => {
    it('sets selected entry', () => {
      const mockEntry = { id: 'entry-1', title: 'Meeting' } as any;
      useCalendarStore.getState().setSelectedEntry(mockEntry);
      expect(useCalendarStore.getState().selectedEntry).toEqual(mockEntry);
    });

    it('clears selected entry with null', () => {
      const mockEntry = { id: 'entry-1', title: 'Meeting' } as any;
      useCalendarStore.getState().setSelectedEntry(mockEntry);
      useCalendarStore.getState().setSelectedEntry(null);
      expect(useCalendarStore.getState().selectedEntry).toBeNull();
    });
  });

  describe('toggleCalendarVisibility', () => {
    it('adds calendar id to visible set', () => {
      useCalendarStore.getState().toggleCalendarVisibility('cal-1');
      expect(useCalendarStore.getState().visibleCalendarIds.has('cal-1')).toBe(true);
    });

    it('removes calendar id from visible set when already present', () => {
      useCalendarStore.getState().toggleCalendarVisibility('cal-1');
      useCalendarStore.getState().toggleCalendarVisibility('cal-1');
      expect(useCalendarStore.getState().visibleCalendarIds.has('cal-1')).toBe(false);
    });

    it('does not affect other calendar ids', () => {
      useCalendarStore.getState().toggleCalendarVisibility('cal-1');
      useCalendarStore.getState().toggleCalendarVisibility('cal-2');
      useCalendarStore.getState().toggleCalendarVisibility('cal-1');
      expect(useCalendarStore.getState().visibleCalendarIds.has('cal-2')).toBe(true);
      expect(useCalendarStore.getState().visibleCalendarIds.has('cal-1')).toBe(false);
    });
  });

  describe('setVisibleMonth', () => {
    it('normalizes date to start of month', () => {
      useCalendarStore.getState().setVisibleMonth(new Date(2024, 5, 15));
      expect(useCalendarStore.getState().visibleMonth.getDate()).toBe(1);
      expect(useCalendarStore.getState().visibleMonth.getMonth()).toBe(5);
    });
  });

  describe('setVisibleDay', () => {
    it('normalizes date to start of day (midnight)', () => {
      useCalendarStore.getState().setVisibleDay(new Date(2024, 5, 15, 14, 30, 45));
      expect(useCalendarStore.getState().visibleDay.getHours()).toBe(0);
      expect(useCalendarStore.getState().visibleDay.getMinutes()).toBe(0);
      expect(useCalendarStore.getState().visibleDay.getSeconds()).toBe(0);
    });
  });

  describe('setRangeStart', () => {
    it('sets range start to start of day', () => {
      useCalendarStore.getState().setRangeStart(new Date(2024, 5, 15, 14, 30));
      expect(useCalendarStore.getState().rangeStart?.getHours()).toBe(0);
      expect(useCalendarStore.getState().rangeStart?.getDate()).toBe(15);
    });

    it('sets range start to null', () => {
      useCalendarStore.getState().setRangeStart(null);
      expect(useCalendarStore.getState().rangeStart).toBeNull();
    });
  });

  describe('setRangeEnd', () => {
    it('sets range end to start of day', () => {
      useCalendarStore.getState().setRangeEnd(new Date(2024, 5, 20, 16, 45));
      expect(useCalendarStore.getState().rangeEnd?.getHours()).toBe(0);
      expect(useCalendarStore.getState().rangeEnd?.getDate()).toBe(20);
    });

    it('sets range end to null', () => {
      useCalendarStore.getState().setRangeEnd(null);
      expect(useCalendarStore.getState().rangeEnd).toBeNull();
    });
  });
});
