// Integration: javascript_database and javascript_log_in_with_replit blueprints
import {
  users,
  guards,
  certifications,
  vehicles,
  customers,
  sites,
  shifts,
  shiftAssignments,
  notifications,
  guardConstraints,
  sitePreferences,
  trainingCourses,
  holidays,
  holidayAssignments,
  absences,
  absenceAffectedShifts,
  contractParameters,
  serviceTypes,
  ccnlSettings,
  type User,
  type UpsertUser,
  type Guard,
  type InsertGuard,
  type Certification,
  type InsertCertification,
  type Vehicle,
  type InsertVehicle,
  type Customer,
  type InsertCustomer,
  type Site,
  type InsertSite,
  type Shift,
  type InsertShift,
  type ShiftAssignment,
  type InsertShiftAssignment,
  type Notification,
  type InsertNotification,
  type GuardConstraints,
  type InsertGuardConstraints,
  type SitePreference,
  type InsertSitePreference,
  type TrainingCourse,
  type InsertTrainingCourse,
  type Holiday,
  type InsertHoliday,
  type HolidayAssignment,
  type InsertHolidayAssignment,
  type Absence,
  type InsertAbsence,
  type AbsenceAffectedShift,
  type InsertAbsenceAffectedShift,
  type ContractParameters,
  type InsertContractParameters,
  type ServiceType,
  type InsertServiceType,
  type CcnlSetting,
  type InsertCcnlSetting,
  type GuardAvailability,
} from "@shared/schema";
import { db } from "./db";
import { eq, and, gte, lte, desc, or, sql as rawSql } from "drizzle-orm";
import { addDays, differenceInHours, parseISO, formatISO } from "date-fns";

export interface IStorage {
  // User operations (Replit Auth required)
  getUser(id: string): Promise<User | undefined>;
  upsertUser(user: UpsertUser): Promise<User>;
  getAllUsers(): Promise<User[]>;
  updateUserRole(id: string, role: "admin" | "coordinator" | "guard" | "client"): Promise<User | undefined>;

  // Guard operations
  getAllGuards(): Promise<Guard[]>;
  getGuard(id: string): Promise<Guard | undefined>;
  createGuard(guard: InsertGuard): Promise<Guard>;
  updateGuard(id: string, guard: Partial<InsertGuard>): Promise<Guard | undefined>;

  // Certification operations
  getCertificationsByGuard(guardId: string): Promise<Certification[]>;
  createCertification(cert: InsertCertification): Promise<Certification>;
  updateCertificationStatus(id: string, status: "valid" | "expiring_soon" | "expired"): Promise<void>;

  // Service Type operations
  getAllServiceTypes(): Promise<ServiceType[]>;
  getServiceType(id: string): Promise<ServiceType | undefined>;
  createServiceType(serviceType: InsertServiceType): Promise<ServiceType>;
  updateServiceType(id: string, serviceType: Partial<InsertServiceType>): Promise<ServiceType | undefined>;
  deleteServiceType(id: string): Promise<ServiceType | undefined>;

  // Customer operations
  getAllCustomers(): Promise<Customer[]>;
  getCustomer(id: string): Promise<Customer | undefined>;
  createCustomer(customer: InsertCustomer): Promise<Customer>;
  updateCustomer(id: string, customer: Partial<InsertCustomer>): Promise<Customer | undefined>;
  deleteCustomer(id: string): Promise<Customer | undefined>;

  // Site operations
  getAllSites(): Promise<Site[]>;
  getSite(id: string): Promise<Site | undefined>;
  createSite(site: InsertSite): Promise<Site>;
  updateSite(id: string, site: Partial<InsertSite>): Promise<Site | undefined>;

  // Shift operations
  getAllShifts(): Promise<Shift[]>;
  getShift(id: string): Promise<Shift | undefined>;
  getActiveShifts(): Promise<Shift[]>;
  createShift(shift: InsertShift): Promise<Shift>;
  updateShiftStatus(id: string, status: "planned" | "active" | "completed" | "cancelled"): Promise<void>;

  // Shift Assignment operations
  getShiftAssignments(shiftId: string): Promise<ShiftAssignment[]>;
  createShiftAssignment(assignment: InsertShiftAssignment): Promise<ShiftAssignment>;

  // Notification operations
  getNotificationsByUser(userId: string): Promise<Notification[]>;
  createNotification(notification: InsertNotification): Promise<Notification>;
  markNotificationAsRead(id: string): Promise<void>;

  // Guard Constraints operations
  getGuardConstraints(guardId: string): Promise<GuardConstraints | undefined>;
  upsertGuardConstraints(constraints: InsertGuardConstraints): Promise<GuardConstraints>;
  
  // Site Preferences operations
  getSitePreferences(siteId: string): Promise<SitePreference[]>;
  createSitePreference(pref: InsertSitePreference): Promise<SitePreference>;
  deleteSitePreference(id: string): Promise<void>;

  // Training Courses operations
  getTrainingCoursesByGuard(guardId: string): Promise<TrainingCourse[]>;
  getAllTrainingCourses(): Promise<TrainingCourse[]>;
  createTrainingCourse(course: InsertTrainingCourse): Promise<TrainingCourse>;
  updateTrainingCourse(id: string, course: Partial<InsertTrainingCourse>): Promise<TrainingCourse | undefined>;
  deleteTrainingCourse(id: string): Promise<void>;

  // Holidays operations
  getAllHolidays(year?: number): Promise<Holiday[]>;
  createHoliday(holiday: InsertHoliday): Promise<Holiday>;
  deleteHoliday(id: string): Promise<void>;

  // Holiday Assignments operations
  getHolidayAssignments(holidayId: string): Promise<HolidayAssignment[]>;
  createHolidayAssignment(assignment: InsertHolidayAssignment): Promise<HolidayAssignment>;
  deleteHolidayAssignment(id: string): Promise<void>;

  // Absences operations
  getAllAbsences(): Promise<Absence[]>;
  getAbsencesByGuard(guardId: string): Promise<Absence[]>;
  createAbsence(absence: InsertAbsence): Promise<Absence>;
  updateAbsence(id: string, absence: Partial<InsertAbsence>): Promise<Absence | undefined>;
  deleteAbsence(id: string): Promise<void>;

  // Absence Affected Shifts operations
  getAffectedShiftsByAbsence(absenceId: string): Promise<AbsenceAffectedShift[]>;
  createAbsenceAffectedShift(affected: InsertAbsenceAffectedShift): Promise<AbsenceAffectedShift>;
  deleteAbsenceAffectedShift(id: string): Promise<void>;

  // Contract Parameters operations
  getContractParameters(): Promise<ContractParameters | undefined>;
  createContractParameters(params: InsertContractParameters): Promise<ContractParameters>;
  updateContractParameters(id: string, params: Partial<InsertContractParameters>): Promise<ContractParameters | undefined>;

  // CCNL Settings operations
  getAllCcnlSettings(): Promise<CcnlSetting[]>;
  getCcnlSetting(key: string): Promise<CcnlSetting | undefined>;
  upsertCcnlSetting(setting: InsertCcnlSetting): Promise<CcnlSetting>;
  deleteCcnlSetting(key: string): Promise<void>;

  // General Planning operations
  getGuardsAvailability(
    siteId: string, 
    location: string, 
    plannedStart: Date, 
    plannedEnd: Date
  ): Promise<GuardAvailability[]>;
  
  // Shift Assignment operations with time slot management
  deleteShiftAssignment(id: string): Promise<void>;
}

export class DatabaseStorage implements IStorage {
  // User operations (Replit Auth required)
  async getUser(id: string): Promise<User | undefined> {
    const [user] = await db.select().from(users).where(eq(users.id, id));
    return user;
  }

  async upsertUser(userData: UpsertUser): Promise<User> {
    // Handle conflicts on both id (primary key) and email (unique constraint)
    // Check if user exists by id or email first
    const existingUser = await db
      .select()
      .from(users)
      .where(
        userData.id 
          ? or(eq(users.id, userData.id), eq(users.email, userData.email || ''))
          : eq(users.email, userData.email || '')
      )
      .limit(1);

    if (existingUser.length > 0) {
      // Update existing user - NEVER change the ID (it's a primary key)
      const [updated] = await db
        .update(users)
        .set({
          ...(userData.email && { email: userData.email }),
          ...(userData.firstName && { firstName: userData.firstName }),
          ...(userData.lastName && { lastName: userData.lastName }),
          ...(userData.profileImageUrl && { profileImageUrl: userData.profileImageUrl }),
          ...(userData.role && { role: userData.role }),
          updatedAt: new Date(),
        })
        .where(eq(users.id, existingUser[0].id))
        .returning();
      return updated;
    } else {
      // Insert new user
      const [user] = await db
        .insert(users)
        .values(userData)
        .returning();
      return user;
    }
  }

  async getAllUsers(): Promise<User[]> {
    return await db.select().from(users).orderBy(desc(users.createdAt));
  }

  async updateUserRole(id: string, role: "admin" | "coordinator" | "guard" | "client"): Promise<User | undefined> {
    const [updated] = await db
      .update(users)
      .set({ role, updatedAt: new Date() })
      .where(eq(users.id, id))
      .returning();
    return updated;
  }

  async deleteUser(id: string): Promise<User | undefined> {
    const [deleted] = await db.delete(users).where(eq(users.id, id)).returning();
    return deleted;
  }

  // Guard operations
  async getAllGuards(): Promise<Guard[]> {
    return await db.select().from(guards);
  }

  async getGuard(id: string): Promise<Guard | undefined> {
    const [guard] = await db.select().from(guards).where(eq(guards.id, id));
    return guard;
  }

  async createGuard(guard: InsertGuard): Promise<Guard> {
    const [newGuard] = await db.insert(guards).values(guard).returning();
    return newGuard;
  }

  async updateGuard(id: string, guardData: Partial<InsertGuard>): Promise<Guard | undefined> {
    const [updated] = await db
      .update(guards)
      .set({ ...guardData, updatedAt: new Date() })
      .where(eq(guards.id, id))
      .returning();
    return updated;
  }

  async deleteGuard(id: string): Promise<Guard | undefined> {
    const [deleted] = await db.delete(guards).where(eq(guards.id, id)).returning();
    return deleted;
  }

  // Vehicle operations
  async getAllVehicles(): Promise<Vehicle[]> {
    return await db.select().from(vehicles).orderBy(desc(vehicles.createdAt));
  }

  async getVehicle(id: string): Promise<Vehicle | undefined> {
    const [vehicle] = await db.select().from(vehicles).where(eq(vehicles.id, id));
    return vehicle;
  }

  async createVehicle(vehicle: InsertVehicle): Promise<Vehicle> {
    const [newVehicle] = await db.insert(vehicles).values(vehicle).returning();
    return newVehicle;
  }

  async updateVehicle(id: string, vehicleData: Partial<InsertVehicle>): Promise<Vehicle | undefined> {
    const [updated] = await db
      .update(vehicles)
      .set({ ...vehicleData, updatedAt: new Date() })
      .where(eq(vehicles.id, id))
      .returning();
    return updated;
  }

  async deleteVehicle(id: string): Promise<Vehicle | undefined> {
    const [deleted] = await db.delete(vehicles).where(eq(vehicles.id, id)).returning();
    return deleted;
  }

  // Certification operations
  async getCertificationsByGuard(guardId: string): Promise<Certification[]> {
    return await db
      .select()
      .from(certifications)
      .where(eq(certifications.guardId, guardId))
      .orderBy(desc(certifications.expiryDate));
  }

  async createCertification(cert: InsertCertification): Promise<Certification> {
    const [newCert] = await db.insert(certifications).values(cert).returning();
    return newCert;
  }

  async updateCertificationStatus(
    id: string,
    status: "valid" | "expiring_soon" | "expired"
  ): Promise<void> {
    await db
      .update(certifications)
      .set({ status })
      .where(eq(certifications.id, id));
  }

  // Service Type operations
  async getAllServiceTypes(): Promise<ServiceType[]> {
    return await db.select().from(serviceTypes).orderBy(desc(serviceTypes.createdAt));
  }

  async getServiceType(id: string): Promise<ServiceType | undefined> {
    const [serviceType] = await db.select().from(serviceTypes).where(eq(serviceTypes.id, id));
    return serviceType;
  }

  async createServiceType(serviceType: InsertServiceType): Promise<ServiceType> {
    const [newServiceType] = await db.insert(serviceTypes).values(serviceType).returning();
    return newServiceType;
  }

  async updateServiceType(id: string, serviceTypeData: Partial<InsertServiceType>): Promise<ServiceType | undefined> {
    const [updated] = await db
      .update(serviceTypes)
      .set({ ...serviceTypeData, updatedAt: new Date() })
      .where(eq(serviceTypes.id, id))
      .returning();
    return updated;
  }

  async deleteServiceType(id: string): Promise<ServiceType | undefined> {
    const [deleted] = await db.delete(serviceTypes).where(eq(serviceTypes.id, id)).returning();
    return deleted;
  }

  // Customer operations
  async getAllCustomers(): Promise<Customer[]> {
    return await db.select().from(customers).orderBy(desc(customers.createdAt));
  }

  async getCustomer(id: string): Promise<Customer | undefined> {
    const [customer] = await db.select().from(customers).where(eq(customers.id, id));
    return customer;
  }

  async createCustomer(customer: InsertCustomer): Promise<Customer> {
    const [newCustomer] = await db.insert(customers).values(customer).returning();
    return newCustomer;
  }

  async updateCustomer(id: string, customerData: Partial<InsertCustomer>): Promise<Customer | undefined> {
    const [updated] = await db
      .update(customers)
      .set({ ...customerData, updatedAt: new Date() })
      .where(eq(customers.id, id))
      .returning();
    return updated;
  }

  async deleteCustomer(id: string): Promise<Customer | undefined> {
    const [deleted] = await db.delete(customers).where(eq(customers.id, id)).returning();
    return deleted;
  }

  // Site operations
  async getAllSites(): Promise<Site[]> {
    return await db.select().from(sites);
  }

  async getSite(id: string): Promise<Site | undefined> {
    const [site] = await db.select().from(sites).where(eq(sites.id, id));
    return site;
  }

  async createSite(site: InsertSite): Promise<Site> {
    const [newSite] = await db.insert(sites).values(site).returning();
    return newSite;
  }

  async updateSite(id: string, siteData: Partial<InsertSite>): Promise<Site | undefined> {
    const [updated] = await db
      .update(sites)
      .set({ ...siteData, updatedAt: new Date() })
      .where(eq(sites.id, id))
      .returning();
    return updated;
  }

  async deleteSite(id: string): Promise<Site | undefined> {
    const [deleted] = await db.delete(sites).where(eq(sites.id, id)).returning();
    return deleted;
  }

  // Shift operations
  async getAllShifts(): Promise<Shift[]> {
    return await db.select().from(shifts).orderBy(desc(shifts.startTime));
  }

  async getShift(id: string): Promise<Shift | undefined> {
    const [shift] = await db.select().from(shifts).where(eq(shifts.id, id));
    return shift;
  }

  async getActiveShifts(): Promise<Shift[]> {
    return await db
      .select()
      .from(shifts)
      .where(eq(shifts.status, "active"))
      .orderBy(desc(shifts.startTime));
  }

  async createShift(shift: InsertShift): Promise<Shift> {
    const [newShift] = await db.insert(shifts).values(shift).returning();
    return newShift;
  }

  async updateShiftStatus(
    id: string,
    status: "planned" | "active" | "completed" | "cancelled"
  ): Promise<void> {
    await db
      .update(shifts)
      .set({ status, updatedAt: new Date() })
      .where(eq(shifts.id, id));
  }

  async updateShift(id: string, shiftData: Partial<InsertShift>): Promise<Shift | undefined> {
    const [updated] = await db
      .update(shifts)
      .set({ ...shiftData, updatedAt: new Date() })
      .where(eq(shifts.id, id))
      .returning();
    return updated;
  }

  async deleteShift(id: string): Promise<Shift | undefined> {
    const [deleted] = await db.delete(shifts).where(eq(shifts.id, id)).returning();
    return deleted;
  }

  // Shift Assignment operations
  async getShiftAssignments(shiftId: string): Promise<ShiftAssignment[]> {
    return await db
      .select()
      .from(shiftAssignments)
      .where(eq(shiftAssignments.shiftId, shiftId));
  }

  async createShiftAssignment(assignment: InsertShiftAssignment): Promise<ShiftAssignment> {
    const [newAssignment] = await db
      .insert(shiftAssignments)
      .values(assignment)
      .returning();
    return newAssignment;
  }

  async deleteShiftAssignment(id: string): Promise<void> {
    await db
      .delete(shiftAssignments)
      .where(eq(shiftAssignments.id, id));
  }

  // Notification operations
  async getNotificationsByUser(userId: string): Promise<Notification[]> {
    return await db
      .select()
      .from(notifications)
      .where(eq(notifications.userId, userId))
      .orderBy(desc(notifications.createdAt));
  }

  async createNotification(notification: InsertNotification): Promise<Notification> {
    const [newNotification] = await db
      .insert(notifications)
      .values(notification)
      .returning();
    return newNotification;
  }

  async markNotificationAsRead(id: string): Promise<void> {
    await db
      .update(notifications)
      .set({ isRead: true })
      .where(eq(notifications.id, id));
  }

  // Guard Constraints operations
  async getGuardConstraints(guardId: string): Promise<GuardConstraints | undefined> {
    const [constraints] = await db
      .select()
      .from(guardConstraints)
      .where(eq(guardConstraints.guardId, guardId));
    return constraints;
  }

  async upsertGuardConstraints(constraintsData: InsertGuardConstraints): Promise<GuardConstraints> {
    const existing = await this.getGuardConstraints(constraintsData.guardId);
    
    if (existing) {
      const [updated] = await db
        .update(guardConstraints)
        .set({ ...constraintsData, updatedAt: new Date() })
        .where(eq(guardConstraints.guardId, constraintsData.guardId))
        .returning();
      return updated;
    } else {
      const [created] = await db
        .insert(guardConstraints)
        .values(constraintsData)
        .returning();
      return created;
    }
  }

  // Site Preferences operations
  async getSitePreferences(siteId: string): Promise<SitePreference[]> {
    return await db
      .select()
      .from(sitePreferences)
      .where(eq(sitePreferences.siteId, siteId));
  }

  async createSitePreference(pref: InsertSitePreference): Promise<SitePreference> {
    const [newPref] = await db.insert(sitePreferences).values(pref).returning();
    return newPref;
  }

  async deleteSitePreference(id: string): Promise<void> {
    await db.delete(sitePreferences).where(eq(sitePreferences.id, id));
  }

  // Training Courses operations
  async getTrainingCoursesByGuard(guardId: string): Promise<TrainingCourse[]> {
    return await db
      .select()
      .from(trainingCourses)
      .where(eq(trainingCourses.guardId, guardId))
      .orderBy(desc(trainingCourses.scheduledDate));
  }

  async getAllTrainingCourses(): Promise<TrainingCourse[]> {
    return await db.select().from(trainingCourses).orderBy(desc(trainingCourses.scheduledDate));
  }

  async createTrainingCourse(course: InsertTrainingCourse): Promise<TrainingCourse> {
    const [newCourse] = await db.insert(trainingCourses).values(course).returning();
    return newCourse;
  }

  async updateTrainingCourse(id: string, courseData: Partial<InsertTrainingCourse>): Promise<TrainingCourse | undefined> {
    const [updated] = await db
      .update(trainingCourses)
      .set(courseData)
      .where(eq(trainingCourses.id, id))
      .returning();
    return updated;
  }

  async deleteTrainingCourse(id: string): Promise<void> {
    await db.delete(trainingCourses).where(eq(trainingCourses.id, id));
  }

  // Holidays operations
  async getAllHolidays(year?: number): Promise<Holiday[]> {
    if (year) {
      return await db
        .select()
        .from(holidays)
        .where(eq(holidays.year, year))
        .orderBy(holidays.date);
    }
    return await db.select().from(holidays).orderBy(holidays.date);
  }

  async createHoliday(holiday: InsertHoliday): Promise<Holiday> {
    const [newHoliday] = await db.insert(holidays).values(holiday).returning();
    return newHoliday;
  }

  async deleteHoliday(id: string): Promise<void> {
    await db.delete(holidays).where(eq(holidays.id, id));
  }

  // Holiday Assignments operations
  async getHolidayAssignments(holidayId: string): Promise<HolidayAssignment[]> {
    return await db
      .select()
      .from(holidayAssignments)
      .where(eq(holidayAssignments.holidayId, holidayId));
  }

  async createHolidayAssignment(assignment: InsertHolidayAssignment): Promise<HolidayAssignment> {
    const [newAssignment] = await db.insert(holidayAssignments).values(assignment).returning();
    return newAssignment;
  }

  async deleteHolidayAssignment(id: string): Promise<void> {
    await db.delete(holidayAssignments).where(eq(holidayAssignments.id, id));
  }

  // Absences operations
  async getAllAbsences(): Promise<Absence[]> {
    return await db.select().from(absences).orderBy(desc(absences.startDate));
  }

  async getAbsencesByGuard(guardId: string): Promise<Absence[]> {
    return await db
      .select()
      .from(absences)
      .where(eq(absences.guardId, guardId))
      .orderBy(desc(absences.startDate));
  }

  async createAbsence(absence: InsertAbsence): Promise<Absence> {
    const [newAbsence] = await db.insert(absences).values(absence).returning();
    return newAbsence;
  }

  async updateAbsence(id: string, absenceData: Partial<InsertAbsence>): Promise<Absence | undefined> {
    const [updated] = await db
      .update(absences)
      .set(absenceData)
      .where(eq(absences.id, id))
      .returning();
    return updated;
  }

  async deleteAbsence(id: string): Promise<void> {
    await db.delete(absences).where(eq(absences.id, id));
  }

  // Absence Affected Shifts operations
  async getAffectedShiftsByAbsence(absenceId: string): Promise<AbsenceAffectedShift[]> {
    return await db
      .select()
      .from(absenceAffectedShifts)
      .where(eq(absenceAffectedShifts.absenceId, absenceId));
  }

  async createAbsenceAffectedShift(affected: InsertAbsenceAffectedShift): Promise<AbsenceAffectedShift> {
    const [newAffected] = await db.insert(absenceAffectedShifts).values(affected).returning();
    return newAffected;
  }

  async deleteAbsenceAffectedShift(id: string): Promise<void> {
    await db.delete(absenceAffectedShifts).where(eq(absenceAffectedShifts.id, id));
  }

  // Contract Parameters operations
  async getContractParameters(): Promise<ContractParameters | undefined> {
    const params = await db.select().from(contractParameters).limit(1);
    return params[0];
  }

  async createContractParameters(params: InsertContractParameters): Promise<ContractParameters> {
    const [newParams] = await db.insert(contractParameters).values(params).returning();
    return newParams;
  }

  async updateContractParameters(id: string, params: Partial<InsertContractParameters>): Promise<ContractParameters | undefined> {
    const [updated] = await db
      .update(contractParameters)
      .set(params)
      .where(eq(contractParameters.id, id))
      .returning();
    return updated;
  }

  // CCNL Settings operations
  async getAllCcnlSettings(): Promise<CcnlSetting[]> {
    return await db.select().from(ccnlSettings);
  }

  async getCcnlSetting(key: string): Promise<CcnlSetting | undefined> {
    const [setting] = await db.select().from(ccnlSettings).where(eq(ccnlSettings.key, key));
    return setting;
  }

  async upsertCcnlSetting(setting: InsertCcnlSetting): Promise<CcnlSetting> {
    const existing = await this.getCcnlSetting(setting.key);
    
    if (existing) {
      const [updated] = await db
        .update(ccnlSettings)
        .set({ ...setting, updatedAt: new Date() })
        .where(eq(ccnlSettings.key, setting.key))
        .returning();
      return updated;
    } else {
      const [newSetting] = await db.insert(ccnlSettings).values(setting).returning();
      return newSetting;
    }
  }

  async deleteCcnlSetting(key: string): Promise<void> {
    await db.delete(ccnlSettings).where(eq(ccnlSettings.key, key));
  }

  // General Planning operations with time slot conflict detection
  async getGuardsAvailability(
    siteId: string, 
    location: string, 
    plannedStart: Date, 
    plannedEnd: Date
  ): Promise<GuardAvailability[]> {
    // Helper: Check if two time ranges overlap
    const hasOverlap = (start1: Date, end1: Date, start2: Date, end2: Date): boolean => {
      return start1 < end2 && end1 > start2;
    };
    
    // Helper: Calculate night hours (22:00-06:00)
    const calculateNightHours = (start: Date, end: Date): number => {
      let nightHours = 0;
      const current = new Date(start);
      
      while (current < end) {
        const hour = current.getUTCHours();
        if (hour >= 22 || hour < 6) {
          nightHours += 1;
        }
        current.setHours(current.getHours() + 1);
      }
      
      return nightHours;
    };
    
    // Calculate week boundaries for weekly hours calculation
    const weekStart = new Date(plannedStart);
    weekStart.setDate(plannedStart.getDate() - plannedStart.getDay() + (plannedStart.getDay() === 0 ? -6 : 1));
    weekStart.setHours(0, 0, 0, 0);
    const weekEnd = addDays(weekStart, 6);
    weekEnd.setHours(23, 59, 59, 999);
    
    // Get contract parameters
    let contractParams = await this.getContractParameters();
    if (!contractParams) {
      contractParams = await this.createContractParameters({
        contractType: "CCNL_VIGILANZA_2024",
      });
    }
    
    const maxOrdinaryHours = contractParams.maxHoursPerWeek || 40; // 40h
    const maxOvertimeHours = contractParams.maxOvertimePerWeek || 8; // 8h
    const maxTotalHours = maxOrdinaryHours + maxOvertimeHours; // 48h
    const maxNightHours = contractParams.maxNightHoursPerWeek || 48; // 48h
    const minDailyRest = contractParams.minDailyRestHours || 11; // 11h
    
    // Get site to check requirements
    const site = await this.getSite(siteId);
    if (!site) {
      return [];
    }
    
    // Get all guards from the same location
    const allGuards = await db
      .select()
      .from(guards)
      .where(eq(guards.location, location as any));
    
    // Filter guards by site requirements
    const eligibleGuards = allGuards.filter((guard: Guard) => {
      if (site.requiresArmed && !guard.isArmed) return false;
      if (site.requiresDriverLicense && !guard.hasDriverLicense) return false;
      return true;
    });
    
    const requestedHours = differenceInHours(plannedEnd, plannedStart);
    const requestedNightHours = calculateNightHours(plannedStart, plannedEnd);
    
    // Analyze each guard's availability
    const guardsWithAvailability: GuardAvailability[] = [];
    
    for (const guard of eligibleGuards) {
      // Get all shift assignments for this guard in the week (for weekly hours)
      const weeklyAssignments = await db
        .select({
          id: shiftAssignments.id,
          shiftId: shiftAssignments.shiftId,
          plannedStartTime: shiftAssignments.plannedStartTime,
          plannedEndTime: shiftAssignments.plannedEndTime,
        })
        .from(shiftAssignments)
        .where(
          and(
            eq(shiftAssignments.guardId, guard.id),
            gte(shiftAssignments.plannedStartTime, weekStart),
            lte(shiftAssignments.plannedStartTime, weekEnd)
          )
        )
        .orderBy(desc(shiftAssignments.plannedEndTime));
      
      // Calculate total weekly hours and night hours assigned
      let weeklyHoursAssigned = 0;
      let nightHoursAssigned = 0;
      let lastShiftEnd: Date | null = null;
      
      for (const assignment of weeklyAssignments) {
        const hours = differenceInHours(assignment.plannedEndTime, assignment.plannedStartTime);
        weeklyHoursAssigned += hours;
        nightHoursAssigned += calculateNightHours(assignment.plannedStartTime, assignment.plannedEndTime);
        
        // Track last shift end for rest calculation
        if (!lastShiftEnd || assignment.plannedEndTime > lastShiftEnd) {
          lastShiftEnd = assignment.plannedEndTime;
        }
      }
      
      // Calculate ordinary and overtime hours
      const ordinaryHoursAssigned = Math.min(weeklyHoursAssigned, maxOrdinaryHours);
      const overtimeHoursAssigned = Math.max(0, weeklyHoursAssigned - maxOrdinaryHours);
      const ordinaryHoursRemaining = Math.max(0, maxOrdinaryHours - weeklyHoursAssigned);
      const overtimeHoursRemaining = Math.max(0, maxOvertimeHours - overtimeHoursAssigned);
      const weeklyHoursRemaining = ordinaryHoursRemaining + overtimeHoursRemaining;
      
      // Check if shift requires overtime
      const requiresOvertime = requestedHours > ordinaryHoursRemaining;
      
      // Check for time conflicts with the requested slot
      const conflicts = [];
      const reasons: string[] = [];
      
      for (const assignment of weeklyAssignments) {
        if (hasOverlap(plannedStart, plannedEnd, assignment.plannedStartTime, assignment.plannedEndTime)) {
          // Get site name for conflict
          const [shift] = await db
            .select({ siteName: sites.name })
            .from(shifts)
            .innerJoin(sites, eq(shifts.siteId, sites.id))
            .where(eq(shifts.id, assignment.shiftId));
          
          conflicts.push({
            from: assignment.plannedStartTime,
            to: assignment.plannedEndTime,
            siteName: shift?.siteName || 'Sito sconosciuto',
            shiftId: assignment.shiftId,
          });
        }
      }
      
      // Check rest violation (11h between shifts)
      let hasRestViolation = false;
      if (lastShiftEnd) {
        const hoursSinceLastShift = differenceInHours(plannedStart, lastShiftEnd);
        if (hoursSinceLastShift < minDailyRest) {
          hasRestViolation = true;
          reasons.push(`Riposo insufficiente (${Math.max(0, hoursSinceLastShift).toFixed(1)}h dall'ultimo turno, minimo ${minDailyRest}h)`);
        }
      }
      
      // Determine availability
      let isAvailable = true;
      
      // EXCLUDE guards already assigned on same day/time
      if (conflicts.length > 0) {
        isAvailable = false;
        reasons.push(`Già assegnata in ${conflicts.length} turno/i nello stesso orario`);
      }
      
      // Check if enough hours available (total)
      if (weeklyHoursRemaining < requestedHours) {
        isAvailable = false;
        reasons.push(`Ore settimanali insufficienti (${Math.max(0, weeklyHoursRemaining)}h disponibili, ${requestedHours}h richieste)`);
      }
      
      // Check night hours limit
      if (nightHoursAssigned + requestedNightHours > maxNightHours) {
        isAvailable = false;
        reasons.push(`Ore notturne esaurite (${nightHoursAssigned}h lavorate, max ${maxNightHours}h/settimana)`);
      }
      
      // Rest violation makes guard unavailable
      if (hasRestViolation) {
        isAvailable = false;
      }
      
      // Build guard name from new fields
      const guardName = guard.firstName && guard.lastName
        ? `${guard.firstName} ${guard.lastName}`
        : guard.badgeNumber;
      
      guardsWithAvailability.push({
        guardId: guard.id,
        guardName,
        badgeNumber: guard.badgeNumber,
        weeklyHoursRemaining,
        weeklyHoursAssigned,
        weeklyHoursMax: maxTotalHours,
        ordinaryHoursRemaining,
        overtimeHoursRemaining,
        nightHoursAssigned,
        requiresOvertime,
        hasRestViolation,
        lastShiftEnd,
        isAvailable,
        conflicts,
        unavailabilityReasons: reasons,
      });
    }
    
    // Sort: available with ordinary hours first, then overtime, then unavailable
    guardsWithAvailability.sort((a, b) => {
      if (a.isAvailable && !b.isAvailable) return -1;
      if (!a.isAvailable && b.isAvailable) return 1;
      if (a.isAvailable && b.isAvailable) {
        if (!a.requiresOvertime && b.requiresOvertime) return -1;
        if (a.requiresOvertime && !b.requiresOvertime) return 1;
      }
      return b.weeklyHoursRemaining - a.weeklyHoursRemaining;
    });
    
    return guardsWithAvailability;
  }
}

export const storage = new DatabaseStorage();
