/**
 * Calendar plugin UI store (zustand).
 *
 * Holds view-mode state (day/week/month/range), navigation dates, the list of
 * calendars the user owns / can write to, the active calendar selection,
 * which calendars are visible in the grid, and the currently selected entry
 * for the right-hand detail panel.
 *
 * Server state (entries, kanban board) lives in the API hooks layer - this
 * store only carries view/UI selection state.
 */

import { create } from 'zustand';
import type { Calendar, CalendarEntry } from '@/api/calendar';

export type CalendarViewMode = 'day' | 'week' | 'month' | 'range';

export interface CalendarState {
  /** First day of the visible month (local midnight). */
  visibleMonth: Date;
  /** First day (Monday) of the visible week. */
  visibleWeek: Date;
  /** The visible day in day-view mode. */
  visibleDay: Date;
  /** Start of the date-range view (inclusive). */
  rangeStart: Date | null;
  /** End of the date-range view (inclusive). */
  rangeEnd: Date | null;
  /** Current view mode. */
  viewMode: CalendarViewMode;
  /** Selected calendar id (null = first available). */
  activeCalendarId: string | null;
  /** Cached calendar list (filled by fetchCalendars()). */
  calendars: Calendar[];
  /** Currently selected entry for the detail panel. */
  selectedEntry: CalendarEntry | null;
  /** Set of calendar ids whose entries are shown in the grid (empty = all). */
  visibleCalendarIds: Set<string>;

  setVisibleMonth: (date: Date) => void;
  setVisibleWeek: (date: Date) => void;
  setVisibleDay: (date: Date) => void;
  setRangeStart: (date: Date | null) => void;
  setRangeEnd: (date: Date | null) => void;
  setViewMode: (mode: CalendarViewMode) => void;
  goToNextMonth: () => void;
  goToPrevMonth: () => void;
  goToNextWeek: () => void;
  goToPrevWeek: () => void;
  goToNextDay: () => void;
  goToPrevDay: () => void;
  goToToday: () => void;
  setActiveCalendarId: (id: string | null) => void;
  setCalendars: (calendars: Calendar[]) => void;
  setSelectedEntry: (entry: CalendarEntry | null) => void;
  toggleCalendarVisibility: (id: string) => void;
}

function startOfMonth(d: Date): Date {
  return new Date(d.getFullYear(), d.getMonth(), 1);
}

/** Return the Monday of the week containing `d`. */
function startOfWeek(d: Date): Date {
  const dayOfWeek = (d.getDay() + 6) % 7; // 0 = Monday
  const start = new Date(d);
  start.setDate(d.getDate() - dayOfWeek);
  start.setHours(0, 0, 0, 0);
  return start;
}

function startOfDay(d: Date): Date {
  return new Date(d.getFullYear(), d.getMonth(), d.getDate());
}

const today = new Date();

export const useCalendarStore = create<CalendarState>((set) => ({
  visibleMonth: startOfMonth(today),
  visibleWeek: startOfWeek(today),
  visibleDay: startOfDay(today),
  rangeStart: startOfDay(today),
  rangeEnd: new Date(today.getFullYear(), today.getMonth(), today.getDate() + 30),
  viewMode: 'month',
  activeCalendarId: null,
  calendars: [],
  selectedEntry: null,
  visibleCalendarIds: new Set<string>(),

  setVisibleMonth: (date) => set({ visibleMonth: startOfMonth(date) }),
  setVisibleWeek: (date) => set({ visibleWeek: startOfWeek(date) }),
  setVisibleDay: (date) => set({ visibleDay: startOfDay(date) }),
  setRangeStart: (date) => set({ rangeStart: date ? startOfDay(date) : null }),
  setRangeEnd: (date) => set({ rangeEnd: date ? startOfDay(date) : null }),
  setViewMode: (mode) => set({ viewMode: mode }),

  goToNextMonth: () =>
    set((s) => {
      const next = new Date(s.visibleMonth);
      next.setMonth(next.getMonth() + 1);
      return { visibleMonth: next };
    }),
  goToPrevMonth: () =>
    set((s) => {
      const next = new Date(s.visibleMonth);
      next.setMonth(next.getMonth() - 1);
      return { visibleMonth: next };
    }),
  goToNextWeek: () =>
    set((s) => {
      const next = new Date(s.visibleWeek);
      next.setDate(next.getDate() + 7);
      return { visibleWeek: next };
    }),
  goToPrevWeek: () =>
    set((s) => {
      const next = new Date(s.visibleWeek);
      next.setDate(next.getDate() - 7);
      return { visibleWeek: next };
    }),
  goToNextDay: () =>
    set((s) => {
      const next = new Date(s.visibleDay);
      next.setDate(next.getDate() + 1);
      return { visibleDay: next };
    }),
  goToPrevDay: () =>
    set((s) => {
      const next = new Date(s.visibleDay);
      next.setDate(next.getDate() - 1);
      return { visibleDay: next };
    }),

  goToToday: () =>
    set({
      visibleMonth: startOfMonth(new Date()),
      visibleWeek: startOfWeek(new Date()),
      visibleDay: startOfDay(new Date()),
    }),

  setActiveCalendarId: (id) => set({ activeCalendarId: id }),
  setCalendars: (calendars) => set({ calendars }),
  setSelectedEntry: (entry) => set({ selectedEntry: entry }),
  toggleCalendarVisibility: (id) =>
    set((s) => {
      const next = new Set(s.visibleCalendarIds);
      if (next.has(id)) {
        next.delete(id);
      } else {
        next.add(id);
      }
      return { visibleCalendarIds: next };
    }),
}));
