import { sql } from "drizzle-orm";
import { relations } from "drizzle-orm";
import {
  pgTable,
  varchar,
  text,
  timestamp,
  index,
  uniqueIndex,
  jsonb,
  boolean,
  integer,
  date,
  pgEnum,
} from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { z } from "zod";

// ============= ENUMS =============

export const userRoleEnum = pgEnum("user_role", [
  "admin",
  "coordinator",
  "guard",
  "client",
]);

export const shiftTypeEnum = pgEnum("shift_type", [
  "fixed_post",      // Presidio fisso
  "patrol",          // Pattugliamento/ronde
  "night_inspection", // Ispettorato notturno
  "quick_response",   // Pronto intervento
]);

export const shiftStatusEnum = pgEnum("shift_status", [
  "planned",
  "active",
  "completed",
  "cancelled",
]);

export const certificationStatusEnum = pgEnum("certification_status", [
  "valid",
  "expiring_soon", // < 30 days
  "expired",
]);

export const shiftPreferenceEnum = pgEnum("shift_preference", [
  "morning",    // 06:00-14:00
  "afternoon",  // 14:00-22:00
  "night",      // 22:00-06:00
  "any",
]);

export const absenceTypeEnum = pgEnum("absence_type", [
  "sick_leave",      // Malattia
  "vacation",        // Ferie
  "personal_leave",  // Permesso
  "injury",          // Infortunio
]);

export const trainingStatusEnum = pgEnum("training_status", [
  "scheduled",
  "completed",
  "expired",
  "cancelled",
]);

export const sitePreferenceTypeEnum = pgEnum("site_preference_type", [
  "preferred",    // Continuità - operatore preferito per questo sito
  "blacklisted",  // Non assegnare mai questo operatore a questo sito
]);

export const vehicleStatusEnum = pgEnum("vehicle_status", [
  "available",    // Disponibile
  "in_use",       // In uso
  "maintenance",  // In manutenzione
  "out_of_service", // Fuori servizio
]);

export const vehicleTypeEnum = pgEnum("vehicle_type", [
  "car",          // Auto
  "van",          // Furgone
  "motorcycle",   // Moto
  "suv",          // SUV
]);

export const locationEnum = pgEnum("location", [
  "roccapiemonte", // Sede Roccapiemonte (Salerno)
  "milano",        // Sede Milano
  "roma",          // Sede Roma
]);

// ============= SESSION & AUTH TABLES (Replit Auth) =============

// Session storage table - mandatory for Replit Auth
export const sessions = pgTable(
  "sessions",
  {
    sid: varchar("sid").primaryKey(),
    sess: jsonb("sess").notNull(),
    expire: timestamp("expire").notNull(),
  },
  (table) => [index("IDX_session_expire").on(table.expire)]
);

// User storage table - mandatory for Replit Auth
export const users = pgTable("users", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  email: varchar("email").unique(),
  firstName: varchar("first_name"),
  lastName: varchar("last_name"),
  profileImageUrl: varchar("profile_image_url"),
  passwordHash: varchar("password_hash"), // For local auth - bcrypt hash
  role: userRoleEnum("role").notNull().default("guard"),
  createdAt: timestamp("created_at").defaultNow(),
  updatedAt: timestamp("updated_at").defaultNow(),
});

// ============= GUARDS & CERTIFICATIONS =============

export const guards = pgTable("guards", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  userId: varchar("user_id").references(() => users.id),
  
  // Anagrafica
  firstName: varchar("first_name").notNull(),
  lastName: varchar("last_name").notNull(),
  email: varchar("email"),
  badgeNumber: varchar("badge_number").notNull().unique(),
  phoneNumber: varchar("phone_number"),
  location: locationEnum("location").notNull().default("roccapiemonte"), // Sede di appartenenza
  
  // Skills
  isArmed: boolean("is_armed").default(false),
  hasFireSafety: boolean("has_fire_safety").default(false),
  hasFirstAid: boolean("has_first_aid").default(false),
  hasDriverLicense: boolean("has_driver_license").default(false),
  languages: text("languages").array(),
  
  createdAt: timestamp("created_at").defaultNow(),
  updatedAt: timestamp("updated_at").defaultNow(),
});

export const certifications = pgTable("certifications", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  guardId: varchar("guard_id").notNull().references(() => guards.id, { onDelete: "cascade" }),
  type: varchar("type").notNull(), // porto_armi, medical_exam, training_course
  name: varchar("name").notNull(),
  issueDate: date("issue_date").notNull(),
  expiryDate: date("expiry_date").notNull(),
  status: certificationStatusEnum("status").notNull().default("valid"),
  documentUrl: varchar("document_url"),
  createdAt: timestamp("created_at").defaultNow(),
});

// ============= VEHICLES (PARCO AUTOMEZZI) =============

export const vehicles = pgTable("vehicles", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  licensePlate: varchar("license_plate").notNull().unique(), // Targa
  brand: varchar("brand").notNull(), // Marca (es: Fiat, Volkswagen)
  model: varchar("model").notNull(), // Modello
  vehicleType: vehicleTypeEnum("vehicle_type").notNull(),
  year: integer("year"), // Anno immatricolazione
  location: locationEnum("location").notNull().default("roccapiemonte"), // Sede di appartenenza
  
  // Assegnazione
  assignedGuardId: varchar("assigned_guard_id").references(() => guards.id, { onDelete: "set null" }),
  
  // Stato e manutenzione
  status: vehicleStatusEnum("status").notNull().default("available"),
  lastMaintenanceDate: date("last_maintenance_date"),
  nextMaintenanceDate: date("next_maintenance_date"),
  mileage: integer("mileage"), // Chilometraggio
  
  notes: text("notes"),
  createdAt: timestamp("created_at").defaultNow(),
  updatedAt: timestamp("updated_at").defaultNow(),
});

// ============= SERVICE TYPES =============

export const serviceTypes = pgTable("service_types", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  code: varchar("code").notNull().unique(), // fixed_post, patrol, etc.
  label: varchar("label").notNull(), // Presidio Fisso, Pattugliamento, etc.
  description: text("description"), // Descrizione dettagliata
  icon: varchar("icon").notNull().default("Building2"), // Nome icona Lucide
  color: varchar("color").notNull().default("blue"), // blue, green, purple, orange
  
  // Parametri specifici per tipo servizio
  fixedPostHours: integer("fixed_post_hours"), // Ore presidio fisso (es. 8, 12)
  patrolPassages: integer("patrol_passages"), // Numero passaggi pattugliamento (es. 3, 5)
  inspectionFrequency: integer("inspection_frequency"), // Frequenza ispezioni in minuti
  responseTimeMinutes: integer("response_time_minutes"), // Tempo risposta pronto intervento
  
  isActive: boolean("is_active").default(true),
  createdAt: timestamp("created_at").defaultNow(),
  updatedAt: timestamp("updated_at").defaultNow(),
});

// ============= CUSTOMERS =============

export const customers = pgTable("customers", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  name: varchar("name").notNull(),
  businessName: varchar("business_name"), // Ragione sociale
  vatNumber: varchar("vat_number"), // Partita IVA
  fiscalCode: varchar("fiscal_code"), // Codice fiscale
  address: varchar("address"),
  city: varchar("city"),
  province: varchar("province"),
  zipCode: varchar("zip_code"),
  phone: varchar("phone"),
  email: varchar("email"),
  pec: varchar("pec"), // PEC (Posta Elettronica Certificata)
  contactPerson: varchar("contact_person"), // Referente
  notes: text("notes"),
  isActive: boolean("is_active").default(true),
  createdAt: timestamp("created_at").defaultNow(),
  updatedAt: timestamp("updated_at").defaultNow(),
});

// ============= SITES & CONTRACTS =============

export const sites = pgTable("sites", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  name: varchar("name").notNull(),
  address: varchar("address").notNull(),
  customerId: varchar("customer_id").references(() => customers.id),
  location: locationEnum("location").notNull().default("roccapiemonte"), // Sede gestionale
  
  // Service requirements
  serviceTypeId: varchar("service_type_id").references(() => serviceTypes.id),
  shiftType: shiftTypeEnum("shift_type"), // Optional - can be derived from service type
  minGuards: integer("min_guards").notNull().default(1),
  requiresArmed: boolean("requires_armed").default(false),
  requiresDriverLicense: boolean("requires_driver_license").default(false),
  
  // Orari servizio (formato HH:MM, es. "08:00", "20:00")
  serviceStartTime: varchar("service_start_time"), // Orario inizio servizio
  serviceEndTime: varchar("service_end_time"), // Orario fine servizio
  
  // Dati contrattuali
  contractReference: varchar("contract_reference"), // Riferimento/numero contratto
  contractStartDate: date("contract_start_date"), // Data inizio contratto
  contractEndDate: date("contract_end_date"), // Data fine contratto
  
  // Coordinates for geofencing (future use)
  latitude: varchar("latitude"),
  longitude: varchar("longitude"),
  
  isActive: boolean("is_active").default(true),
  createdAt: timestamp("created_at").defaultNow(),
  updatedAt: timestamp("updated_at").defaultNow(),
});

// ============= SHIFTS & ASSIGNMENTS =============

export const shifts = pgTable("shifts", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  siteId: varchar("site_id").notNull().references(() => sites.id, { onDelete: "cascade" }),
  
  startTime: timestamp("start_time").notNull(),
  endTime: timestamp("end_time").notNull(),
  status: shiftStatusEnum("status").notNull().default("planned"),
  
  // Veicolo assegnato al turno (opzionale)
  vehicleId: varchar("vehicle_id").references(() => vehicles.id, { onDelete: "set null" }),
  
  notes: text("notes"),
  createdAt: timestamp("created_at").defaultNow(),
  updatedAt: timestamp("updated_at").defaultNow(),
});

export const shiftAssignments = pgTable("shift_assignments", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  shiftId: varchar("shift_id").notNull().references(() => shifts.id, { onDelete: "cascade" }),
  guardId: varchar("guard_id").notNull().references(() => guards.id, { onDelete: "cascade" }),
  
  // Planned shift times (when the guard is scheduled to work)
  plannedStartTime: timestamp("planned_start_time").notNull(),
  plannedEndTime: timestamp("planned_end_time").notNull(),
  
  assignedAt: timestamp("assigned_at").defaultNow(),
  confirmedAt: timestamp("confirmed_at"),
  
  // Actual check-in/out times (recorded when guard clocks in/out)
  checkInTime: timestamp("check_in_time"),
  checkOutTime: timestamp("check_out_time"),
});

// ============= CCNL SETTINGS =============

export const ccnlSettings = pgTable("ccnl_settings", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  key: varchar("key").notNull().unique(),
  value: varchar("value").notNull(),
  description: text("description"),
  createdAt: timestamp("created_at").defaultNow(),
  updatedAt: timestamp("updated_at").defaultNow(),
});

// ============= NOTIFICATIONS =============

export const notifications = pgTable("notifications", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  userId: varchar("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
  
  title: varchar("title").notNull(),
  message: text("message").notNull(),
  type: varchar("type").notNull(), // shift_assigned, certification_expiring, shift_reminder
  
  isRead: boolean("is_read").default(false),
  relatedEntityId: varchar("related_entity_id"), // shift_id, certification_id, etc.
  
  createdAt: timestamp("created_at").defaultNow(),
});

// ============= GUARD CONSTRAINTS & PREFERENCES =============

export const guardConstraints = pgTable("guard_constraints", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  guardId: varchar("guard_id").notNull().references(() => guards.id, { onDelete: "cascade" }).unique(),
  
  // Preferenze turni
  preferredShiftType: shiftPreferenceEnum("preferred_shift_type").default("any"),
  
  // Limiti contrattuali personalizzati (se diversi dal CCNL base)
  maxHoursPerDay: integer("max_hours_per_day").default(10), // 8 + 2 straordinario
  maxHoursPerWeek: integer("max_hours_per_week").default(48), // 40 + 8 straordinario
  
  // Giorni riposo preferiti (1=Lunedì...7=Domenica)
  preferredDaysOff: integer("preferred_days_off").array(),
  
  // Disponibilità festività
  availableOnHolidays: boolean("available_on_holidays").default(true),
  
  // Note aggiuntive
  notes: text("notes"),
  
  updatedAt: timestamp("updated_at").defaultNow(),
});

// ============= SITE PREFERENCES =============

export const sitePreferences = pgTable("site_preferences", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  siteId: varchar("site_id").notNull().references(() => sites.id, { onDelete: "cascade" }),
  guardId: varchar("guard_id").notNull().references(() => guards.id, { onDelete: "cascade" }),
  
  // Preferenza: preferred = continuità, blacklisted = non assegnare mai
  preference: sitePreferenceTypeEnum("preference").notNull(),
  priority: integer("priority").default(0), // Più alto = più preferito
  
  reason: text("reason"), // Motivazione preferenza/blacklist
  createdAt: timestamp("created_at").defaultNow(),
}, (table) => ({
  // Unique constraint: una sola preferenza per coppia sito-guardia
  uniqueSiteGuard: uniqueIndex("unique_site_guard_preference").on(table.siteId, table.guardId),
}));

// ============= CONTRACT PARAMETERS (CCNL) =============

export const contractParameters = pgTable("contract_parameters", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  
  // Identificatore tipo contratto (default = CCNL Vigilanza Privata)
  contractType: varchar("contract_type").notNull().unique().default("CCNL_VIGILANZA_2023"),
  
  // Limiti orari
  maxHoursPerDay: integer("max_hours_per_day").notNull().default(8),
  maxOvertimePerDay: integer("max_overtime_per_day").notNull().default(2),
  maxHoursPerWeek: integer("max_hours_per_week").notNull().default(40),
  maxOvertimePerWeek: integer("max_overtime_per_week").notNull().default(8),
  
  // Riposi obbligatori
  minDailyRestHours: integer("min_daily_rest_hours").notNull().default(11),
  minDailyRestHoursReduced: integer("min_daily_rest_hours_reduced").notNull().default(9), // Deroga CCNL
  maxDailyRestReductionsPerMonth: integer("max_daily_rest_reductions_per_month").notNull().default(3),
  maxDailyRestReductionsPerYear: integer("max_daily_rest_reductions_per_year").notNull().default(12),
  minWeeklyRestHours: integer("min_weekly_rest_hours").notNull().default(24),
  
  // Pause obbligatorie
  pauseMinutesIfOver6Hours: integer("pause_minutes_if_over_6_hours").notNull().default(10),
  
  // Buoni pasto
  mealVoucherEnabled: boolean("meal_voucher_enabled").default(true), // Buoni pasto attivi
  mealVoucherAfterHours: integer("meal_voucher_after_hours").default(6), // Ore minime per diritto buono pasto
  mealVoucherAmount: integer("meal_voucher_amount").default(8), // Importo buono pasto in euro (facoltativo)
  
  // Limiti notturni (22:00-06:00)
  maxNightHoursPerWeek: integer("max_night_hours_per_week").default(48),
  
  // Maggiorazioni (percentuali)
  holidayPayIncrease: integer("holiday_pay_increase").default(30), // +30% festivi
  nightPayIncrease: integer("night_pay_increase").default(20), // +20% notturni
  overtimePayIncrease: integer("overtime_pay_increase").default(15), // +15% straordinari
  
  createdAt: timestamp("created_at").defaultNow(),
  updatedAt: timestamp("updated_at").defaultNow(),
});

// ============= TRAINING & COURSES =============

export const trainingCourses = pgTable("training_courses", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  guardId: varchar("guard_id").notNull().references(() => guards.id, { onDelete: "cascade" }),
  
  courseName: varchar("course_name").notNull(),
  courseType: varchar("course_type").notNull(), // "mandatory" | "optional"
  
  scheduledDate: date("scheduled_date"),
  completionDate: date("completion_date"),
  expiryDate: date("expiry_date"), // Per corsi con scadenza (es. primo soccorso)
  
  status: trainingStatusEnum("status").notNull().default("scheduled"),
  certificateUrl: varchar("certificate_url"),
  
  provider: varchar("provider"), // Ente formatore
  hours: integer("hours"), // Ore corso
  notes: text("notes"),
  
  createdAt: timestamp("created_at").defaultNow(),
});

// ============= HOLIDAYS =============

export const holidays = pgTable("holidays", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  
  name: varchar("name").notNull(), // "Natale", "Capodanno", "1 Maggio", etc.
  date: date("date").notNull(),
  year: integer("year").notNull(), // Anno specifico per tracking rotazioni
  isNational: boolean("is_national").default(true), // Nazionale o regionale
  
  createdAt: timestamp("created_at").defaultNow(),
}, (table) => ({
  // Unique constraint: una festività per data e anno
  uniqueDateYear: uniqueIndex("unique_holiday_date_year").on(table.date, table.year),
}));

// Join table per tracking rotazioni festività con integrità referenziale
export const holidayAssignments = pgTable("holiday_assignments", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  holidayId: varchar("holiday_id").notNull().references(() => holidays.id, { onDelete: "cascade" }),
  guardId: varchar("guard_id").notNull().references(() => guards.id, { onDelete: "cascade" }),
  shiftId: varchar("shift_id").references(() => shifts.id, { onDelete: "set null" }), // Turno specifico lavorato
  
  createdAt: timestamp("created_at").defaultNow(),
}, (table) => ({
  // Unique constraint: una guardia non può essere assegnata due volte alla stessa festività
  uniqueHolidayGuard: uniqueIndex("unique_holiday_guard").on(table.holidayId, table.guardId),
}));

// ============= ABSENCES & SUBSTITUTIONS =============

export const absences = pgTable("absences", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  guardId: varchar("guard_id").notNull().references(() => guards.id, { onDelete: "cascade" }),
  
  type: absenceTypeEnum("type").notNull(),
  startDate: date("start_date").notNull(),
  endDate: date("end_date").notNull(),
  
  // Documentazione
  certificateUrl: varchar("certificate_url"), // Certificato medico, etc.
  notes: text("notes"),
  
  // Se approvata e serve sostituto
  isApproved: boolean("is_approved").default(false),
  needsSubstitute: boolean("needs_substitute").default(true),
  substituteGuardId: varchar("substitute_guard_id").references(() => guards.id),
  
  createdAt: timestamp("created_at").defaultNow(),
  approvedAt: timestamp("approved_at"),
  approvedBy: varchar("approved_by").references(() => users.id),
});

// Join table per tracking turni impattati da assenze (per sistema sostituzione)
export const absenceAffectedShifts = pgTable("absence_affected_shifts", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  absenceId: varchar("absence_id").notNull().references(() => absences.id, { onDelete: "cascade" }),
  shiftId: varchar("shift_id").notNull().references(() => shifts.id, { onDelete: "cascade" }),
  
  // Se sostituto trovato
  isSubstituted: boolean("is_substituted").default(false),
  
  createdAt: timestamp("created_at").defaultNow(),
}, (table) => ({
  // Unique: uno shift non può essere impattato due volte dalla stessa assenza
  uniqueAbsenceShift: uniqueIndex("unique_absence_shift").on(table.absenceId, table.shiftId),
}));

// ============= RELATIONS =============

export const usersRelations = relations(users, ({ one, many }) => ({
  guard: one(guards, {
    fields: [users.id],
    references: [guards.userId],
  }),
  notifications: many(notifications),
}));

export const guardsRelations = relations(guards, ({ one, many }) => ({
  user: one(users, {
    fields: [guards.userId],
    references: [users.id],
  }),
  certifications: many(certifications),
  shiftAssignments: many(shiftAssignments),
  constraints: one(guardConstraints),
  sitePreferences: many(sitePreferences),
  trainingCourses: many(trainingCourses),
  absences: many(absences),
  assignedVehicles: many(vehicles),
}));

export const vehiclesRelations = relations(vehicles, ({ one }) => ({
  assignedGuard: one(guards, {
    fields: [vehicles.assignedGuardId],
    references: [guards.id],
  }),
}));

export const certificationsRelations = relations(certifications, ({ one }) => ({
  guard: one(guards, {
    fields: [certifications.guardId],
    references: [guards.id],
  }),
}));

export const customersRelations = relations(customers, ({ many }) => ({
  sites: many(sites),
}));

export const sitesRelations = relations(sites, ({ one, many }) => ({
  customer: one(customers, {
    fields: [sites.customerId],
    references: [customers.id],
  }),
  shifts: many(shifts),
  preferences: many(sitePreferences),
}));

export const shiftsRelations = relations(shifts, ({ one, many }) => ({
  site: one(sites, {
    fields: [shifts.siteId],
    references: [sites.id],
  }),
  vehicle: one(vehicles, {
    fields: [shifts.vehicleId],
    references: [vehicles.id],
  }),
  assignments: many(shiftAssignments),
}));

export const shiftAssignmentsRelations = relations(shiftAssignments, ({ one }) => ({
  shift: one(shifts, {
    fields: [shiftAssignments.shiftId],
    references: [shifts.id],
  }),
  guard: one(guards, {
    fields: [shiftAssignments.guardId],
    references: [guards.id],
  }),
}));

export const notificationsRelations = relations(notifications, ({ one }) => ({
  user: one(users, {
    fields: [notifications.userId],
    references: [users.id],
  }),
}));

export const guardConstraintsRelations = relations(guardConstraints, ({ one }) => ({
  guard: one(guards, {
    fields: [guardConstraints.guardId],
    references: [guards.id],
  }),
}));

export const sitePreferencesRelations = relations(sitePreferences, ({ one }) => ({
  site: one(sites, {
    fields: [sitePreferences.siteId],
    references: [sites.id],
  }),
  guard: one(guards, {
    fields: [sitePreferences.guardId],
    references: [guards.id],
  }),
}));

export const trainingCoursesRelations = relations(trainingCourses, ({ one }) => ({
  guard: one(guards, {
    fields: [trainingCourses.guardId],
    references: [guards.id],
  }),
}));

export const absencesRelations = relations(absences, ({ one, many }) => ({
  guard: one(guards, {
    fields: [absences.guardId],
    references: [guards.id],
  }),
  substituteGuard: one(guards, {
    fields: [absences.substituteGuardId],
    references: [guards.id],
  }),
  approver: one(users, {
    fields: [absences.approvedBy],
    references: [users.id],
  }),
  affectedShifts: many(absenceAffectedShifts),
}));

export const absenceAffectedShiftsRelations = relations(absenceAffectedShifts, ({ one }) => ({
  absence: one(absences, {
    fields: [absenceAffectedShifts.absenceId],
    references: [absences.id],
  }),
  shift: one(shifts, {
    fields: [absenceAffectedShifts.shiftId],
    references: [shifts.id],
  }),
}));

export const holidaysRelations = relations(holidays, ({ many }) => ({
  assignments: many(holidayAssignments),
}));

export const holidayAssignmentsRelations = relations(holidayAssignments, ({ one }) => ({
  holiday: one(holidays, {
    fields: [holidayAssignments.holidayId],
    references: [holidays.id],
  }),
  guard: one(guards, {
    fields: [holidayAssignments.guardId],
    references: [guards.id],
  }),
  shift: one(shifts, {
    fields: [holidayAssignments.shiftId],
    references: [shifts.id],
  }),
}));

// ============= INSERT SCHEMAS =============

export const insertUserSchema = createInsertSchema(users).pick({
  email: true,
  firstName: true,
  lastName: true,
  profileImageUrl: true,
  passwordHash: true,
  role: true,
});

// Form schema with plain password (will be hashed on backend)
export const insertUserFormSchema = z.object({
  email: z.string().email("Email non valida"),
  firstName: z.string().min(1, "Nome obbligatorio"),
  lastName: z.string().min(1, "Cognome obbligatorio"),
  password: z.string().min(6, "Password minimo 6 caratteri"),
  role: z.enum(["admin", "coordinator", "guard", "client"]).default("guard"),
});

// Update user form schema (password optional)
export const updateUserFormSchema = z.object({
  email: z.string().email("Email non valida").optional(),
  firstName: z.string().min(1, "Nome obbligatorio").optional(),
  lastName: z.string().min(1, "Cognome obbligatorio").optional(),
  password: z.string().min(6, "Password minimo 6 caratteri").optional(),
  role: z.enum(["admin", "coordinator", "guard", "client"]).optional(),
});

export const insertGuardSchema = createInsertSchema(guards).omit({
  id: true,
  createdAt: true,
  updatedAt: true,
}).extend({
  firstName: z.string().min(1, "Nome obbligatorio"),
  lastName: z.string().min(1, "Cognome obbligatorio"),
  email: z.string().email("Email non valida").optional().or(z.literal("")),
  badgeNumber: z.string().min(1, "Matricola obbligatoria"),
  phoneNumber: z.string().optional().or(z.literal("")),
  location: z.enum(["roccapiemonte", "milano", "roma"]),
});

export const insertCertificationSchema = createInsertSchema(certifications).omit({
  id: true,
  createdAt: true,
  status: true,
});

export const insertVehicleSchema = createInsertSchema(vehicles).omit({
  id: true,
  createdAt: true,
  updatedAt: true,
});

export const insertServiceTypeSchema = createInsertSchema(serviceTypes).omit({
  id: true,
  createdAt: true,
  updatedAt: true,
});

export const insertCustomerSchema = createInsertSchema(customers).omit({
  id: true,
  createdAt: true,
  updatedAt: true,
});

export const insertSiteSchema = createInsertSchema(sites).omit({
  id: true,
  createdAt: true,
  updatedAt: true,
});

export const insertShiftSchema = createInsertSchema(shifts).omit({
  id: true,
  createdAt: true,
  updatedAt: true,
});

// Form schema that accepts datetime strings and transforms to Date
export const insertShiftFormSchema = z.object({
  siteId: z.string().min(1, "Sito obbligatorio"),
  startTime: z.string().min(1, "Data inizio obbligatoria").refine((val) => !isNaN(new Date(val).getTime()), {
    message: "Data inizio non valida",
  }).transform((val) => new Date(val)),
  endTime: z.string().min(1, "Data fine obbligatoria").refine((val) => !isNaN(new Date(val).getTime()), {
    message: "Data fine non valida",
  }).transform((val) => new Date(val)),
  status: z.enum(["planned", "active", "completed", "cancelled"]).default("planned"),
});

export const insertShiftAssignmentSchema = createInsertSchema(shiftAssignments)
  .omit({
    id: true,
    assignedAt: true,
  })
  .extend({
    plannedStartTime: z.union([z.string(), z.date()], {
      required_error: "Orario inizio richiesto",
      invalid_type_error: "Orario inizio non valido",
    }).transform((val) => new Date(val)),
    plannedEndTime: z.union([z.string(), z.date()], {
      required_error: "Orario fine richiesto",
      invalid_type_error: "Orario fine non valido",
    }).transform((val) => new Date(val)),
  })
  .refine((data) => data.plannedEndTime > data.plannedStartTime, {
    message: "L'orario di fine deve essere successivo all'orario di inizio",
    path: ["plannedEndTime"],
  });

export const insertCcnlSettingSchema = createInsertSchema(ccnlSettings).omit({
  id: true,
  createdAt: true,
  updatedAt: true,
});

export const insertNotificationSchema = createInsertSchema(notifications).omit({
  id: true,
  createdAt: true,
});

export const insertGuardConstraintsSchema = createInsertSchema(guardConstraints).omit({
  id: true,
  updatedAt: true,
});

export const insertSitePreferenceSchema = createInsertSchema(sitePreferences).omit({
  id: true,
  createdAt: true,
});

export const insertContractParametersSchema = createInsertSchema(contractParameters).omit({
  id: true,
  createdAt: true,
  updatedAt: true,
});

export const insertTrainingCourseSchema = createInsertSchema(trainingCourses).omit({
  id: true,
  createdAt: true,
});

export const insertHolidaySchema = createInsertSchema(holidays).omit({
  id: true,
  createdAt: true,
});

export const insertAbsenceSchema = createInsertSchema(absences).omit({
  id: true,
  createdAt: true,
  approvedAt: true,
});

export const insertHolidayAssignmentSchema = createInsertSchema(holidayAssignments).omit({
  id: true,
  createdAt: true,
});

export const insertAbsenceAffectedShiftSchema = createInsertSchema(absenceAffectedShifts).omit({
  id: true,
  createdAt: true,
});

// ============= TYPES =============

export type UpsertUser = typeof users.$inferInsert;
export type User = typeof users.$inferSelect;

export type InsertGuard = z.infer<typeof insertGuardSchema>;
export type Guard = typeof guards.$inferSelect;

export type InsertCertification = z.infer<typeof insertCertificationSchema>;
export type Certification = typeof certifications.$inferSelect;

export type InsertVehicle = z.infer<typeof insertVehicleSchema>;
export type Vehicle = typeof vehicles.$inferSelect;

export type InsertServiceType = z.infer<typeof insertServiceTypeSchema>;
export type ServiceType = typeof serviceTypes.$inferSelect;

export type InsertCustomer = z.infer<typeof insertCustomerSchema>;
export type Customer = typeof customers.$inferSelect;

export type InsertSite = z.infer<typeof insertSiteSchema>;
export type Site = typeof sites.$inferSelect;

export type InsertShift = z.infer<typeof insertShiftSchema>;
export type Shift = typeof shifts.$inferSelect;

export type InsertShiftAssignment = z.infer<typeof insertShiftAssignmentSchema>;
export type ShiftAssignment = typeof shiftAssignments.$inferSelect;

export type InsertCcnlSetting = z.infer<typeof insertCcnlSettingSchema>;
export type CcnlSetting = typeof ccnlSettings.$inferSelect;

export type InsertNotification = z.infer<typeof insertNotificationSchema>;
export type Notification = typeof notifications.$inferSelect;

export type InsertGuardConstraints = z.infer<typeof insertGuardConstraintsSchema>;
export type GuardConstraints = typeof guardConstraints.$inferSelect;

export type InsertSitePreference = z.infer<typeof insertSitePreferenceSchema>;
export type SitePreference = typeof sitePreferences.$inferSelect;

export type InsertContractParameters = z.infer<typeof insertContractParametersSchema>;
export type ContractParameters = typeof contractParameters.$inferSelect;

export type InsertTrainingCourse = z.infer<typeof insertTrainingCourseSchema>;
export type TrainingCourse = typeof trainingCourses.$inferSelect;

export type InsertHoliday = z.infer<typeof insertHolidaySchema>;
export type Holiday = typeof holidays.$inferSelect;

export type InsertAbsence = z.infer<typeof insertAbsenceSchema>;
export type Absence = typeof absences.$inferSelect;

export type InsertHolidayAssignment = z.infer<typeof insertHolidayAssignmentSchema>;
export type HolidayAssignment = typeof holidayAssignments.$inferSelect;

export type InsertAbsenceAffectedShift = z.infer<typeof insertAbsenceAffectedShiftSchema>;
export type AbsenceAffectedShift = typeof absenceAffectedShifts.$inferSelect;

// ============= EXTENDED TYPES FOR FRONTEND =============

export type GuardWithCertifications = Guard & {
  certifications: Certification[];
  user?: User;
};

export type ShiftWithDetails = Shift & {
  site: Site;
  assignments: (ShiftAssignment & {
    guard: GuardWithCertifications;
  })[];
};

export type SiteWithShifts = Site & {
  shifts: Shift[];
  client?: User;
};

export type GuardWithDetails = Guard & {
  user?: User;
  certifications: Certification[];
  constraints?: GuardConstraints;
  trainingCourses: TrainingCourse[];
  absences: Absence[];
};

export type AbsenceWithDetails = Absence & {
  guard: Guard;
  substituteGuard?: Guard;
  approver?: User;
  affectedShifts: (AbsenceAffectedShift & {
    shift: Shift;
  })[];
};

// ============= DTOs FOR GENERAL PLANNING =============

// DTO per conflitto orario guardia
export const guardConflictSchema = z.object({
  from: z.date(),
  to: z.date(),
  siteName: z.string(),
  shiftId: z.string(),
});

// DTO per disponibilità guardia con controllo conflitti orari
export const guardAvailabilitySchema = z.object({
  guardId: z.string(),
  guardName: z.string(),
  badgeNumber: z.string(),
  weeklyHoursRemaining: z.number(),
  weeklyHoursAssigned: z.number(),
  weeklyHoursMax: z.number(),
  ordinaryHoursRemaining: z.number(), // Ore ordinarie disponibili (max 40h)
  overtimeHoursRemaining: z.number(), // Ore straordinario disponibili (max 8h)
  nightHoursAssigned: z.number(), // Ore notturne lavorate (22:00-06:00)
  requiresOvertime: z.boolean(), // True se richiede straordinario
  hasRestViolation: z.boolean(), // True se viola riposo obbligatorio
  lastShiftEnd: z.date().nullable(), // Fine ultimo turno (per calcolo riposo)
  isAvailable: z.boolean(),
  conflicts: z.array(guardConflictSchema),
  unavailabilityReasons: z.array(z.string()),
});

export type GuardConflict = z.infer<typeof guardConflictSchema>;
export type GuardAvailability = z.infer<typeof guardAvailabilitySchema>;

// DTO per creazione turno multi-giorno dal Planning Generale
export const createMultiDayShiftSchema = z.object({
  siteId: z.string(),
  startDate: z.string(), // YYYY-MM-DD
  days: z.number().min(1).max(7),
  guardId: z.string(),
  shiftType: z.enum(["fixed_post", "patrol", "night_inspection", "quick_response"]).optional(),
});

export type CreateMultiDayShiftRequest = z.infer<typeof createMultiDayShiftSchema>;
