// src/client/entities/shift.ts
// Shift entity - Pinia store and types for schedule management

import { defineStore } from 'pinia';
import { api } from '../shared/api';

// Shift data structure matching backend
export interface Shift {
  id: string;
  date: string;
  userId: string;
  roleAtShift: 'Manager' | 'Maid';
  status: 'Blank' | 'Work' | 'Holiday' | 'Unavailable';
  isApproved: boolean;
  createdBy: string;
  createdAt: string;
  updatedAt: string;
  archivedAt: string | null;
}

// Draft change for Manager mode (local changes before approval)
export interface DraftChange {
  userId: string;
  date: string;
  roleAtShift: 'Manager' | 'Maid';
  status: 'Blank' | 'Work' | 'Holiday' | 'Unavailable';
}

export const useShiftStore = defineStore('shift', {
  state: () => ({
    shifts: [] as Shift[],
    draftChanges: new Map<string, DraftChange>(),
    loading: false,
    error: null as string | null,
  }),

  getters: {
    // Get draft changes count
    draftChangesCount: (state) => state.draftChanges.size,

    // Get draft changes as array
    draftChangesArray: (state) => Array.from(state.draftChanges.values()),
  },

  actions: {
  // Fetch shifts from API
  async fetchShifts(month: number, year: number): Promise<void> {
    this.loading = true;
    this.error = null;
    try {
      const response = await api.get<{ shifts: Shift[] }>(`/schedule/shifts/grid?month=${month}&year=${year}`);
      console.log('[Shift Store] Raw shifts data from API:', response.shifts);
      this.shifts = response.shifts;
    } catch (error: any) {
      this.error = error.message || 'Failed to fetch shifts';
      console.error('[Shift Store] Error fetching shifts:', error);
    } finally {
      this.loading = false;
    }
  },

  // Set cell status - handles Admin vs Manager mode
  async setCellStatus(
    userId: string,
    date: string,
    roleAtShift: 'Manager' | 'Maid',
    status: 'Blank' | 'Work' | 'Holiday' | 'Unavailable',
    currentUserRole: 'ADMIN' | 'MANAGER' | 'MAID'
  ): Promise<void> {
      const dateStr = typeof date === 'string' ? date : new Date(date).toISOString().split('T')[0];

      // Admin mode: Call API immediately
      if (currentUserRole === 'ADMIN') {
        try {
          await api.post('/schedule/shifts/update', {
            shifts: [{ userId, date: new Date(dateStr), roleAtShift, status }],
          });
        } catch (error: any) {
          this.error = error.message || 'Failed to update shift';
          throw error;
        }
      } else {
        // Manager/MAID mode: Update local draft changes
        const key = `${userId}-${dateStr}-${roleAtShift}`;
        this.draftChanges.set(key, {
          userId,
          date: dateStr,
          roleAtShift,
          status,
        });
      }
    },

    // Save all draft changes to API (for Manager mode)
    async saveDraftChanges(): Promise<void> {
      if (this.draftChanges.size === 0) return;

      this.loading = true;
      this.error = null;

      try {
        const shifts = Array.from(this.draftChanges.values()).map((change) => ({
          userId: change.userId,
          date: new Date(change.date),
          roleAtShift: change.roleAtShift,
          status: change.status,
        }));

        await api.post('/schedule/shifts/update', { shifts });

        // Clear draft changes after successful save
        this.draftChanges.clear();
      } catch (error: any) {
        this.error = error.message || 'Failed to save draft changes';
        throw error;
      } finally {
        this.loading = false;
      }
    },

    // Clear draft changes
    clearDraftChanges(): void {
      this.draftChanges.clear();
    },

    // Get draft change for a specific cell
    getDraftChange(userId: string, date: string, roleAtShift: 'Manager' | 'Maid'): DraftChange | undefined {
      const key = `${userId}-${date}-${roleAtShift}`;
      return this.draftChanges.get(key);
    },

    // Legacy methods for backward compatibility
    addShift(shift: Shift) {
      this.shifts.push(shift);
    },
    updateShift(id: string, updates: Partial<Shift>) {
      const index = this.shifts.findIndex((s) => s.id === id);
      if (index !== -1) {
        this.shifts[index] = { ...this.shifts[index], ...updates };
      }
    },
    deleteShift(id: string) {
      this.shifts = this.shifts.filter((s) => s.id !== id);
    },
  },
});
