import { parseISO, isSameDay } from "date-fns";

/**
 * Parses time string (HH:MM or HH:MM AM/PM) into minutes since midnight
 */
const parseTimeToMinutes = (timeStr) => {
  if (!timeStr) return 0;
  
  try {
    const cleanTime = timeStr.trim().toUpperCase();
    let hours, minutes;
    
    if (cleanTime.includes('AM') || cleanTime.includes('PM')) {
      const isPM = cleanTime.includes('PM');
      const timePart = cleanTime.replace(/AM|PM/g, '').trim();
      [hours, minutes] = timePart.split(':').map(Number);
      
      if (isPM && hours !== 12) hours += 12;
      if (!isPM && hours === 12) hours = 0;
    } else {
      [hours, minutes] = cleanTime.split(':').map(Number);
    }
    
    return (hours * 60) + (minutes || 0);
  } catch {
    return 0;
  }
};

/**
 * Checks if a worker is already assigned to an event on a given date
 */
export const getWorkerAssignments = (workerId, events, targetDate) => {
  const targetDateObj = typeof targetDate === 'string' ? parseISO(targetDate) : targetDate;
  
  return events.filter(event => {
    if (!event.assigned_staff || event.status === 'Canceled') return false;
    
    // Check if worker is assigned to this event
    const isAssigned = event.assigned_staff.some(staff => 
      staff.staff_id === workerId || staff.id === workerId
    );
    
    if (!isAssigned) return false;
    
    // Check if event is on the same date
    const eventDate = typeof event.date === 'string' ? parseISO(event.date) : new Date(event.date);
    return isSameDay(eventDate, targetDateObj);
  });
};

/**
 * Checks if two shifts overlap or violate spacing rules
 * Returns: { allowed: boolean, needsOverride: boolean, reason: string, gapMinutes: number }
 */
export const checkShiftConflict = (shift1, shift2) => {
  if (!shift1 || !shift2) {
    return { allowed: true, needsOverride: false, reason: '', gapMinutes: 0 };
  }
  
  // Get time ranges from shifts
  const shift1Start = shift1.roles?.[0]?.start_time || shift1.start_time || '00:00';
  const shift1End = shift1.roles?.[0]?.end_time || shift1.end_time || '23:59';
  const shift2Start = shift2.roles?.[0]?.start_time || shift2.start_time || '00:00';
  const shift2End = shift2.roles?.[0]?.end_time || shift2.end_time || '23:59';
  
  const s1Start = parseTimeToMinutes(shift1Start);
  const s1End = parseTimeToMinutes(shift1End);
  const s2Start = parseTimeToMinutes(shift2Start);
  const s2End = parseTimeToMinutes(shift2End);
  
  // Check for direct overlap
  const overlaps = (s1Start < s2End && s1End > s2Start);
  
  if (overlaps) {
    return {
      allowed: false,
      needsOverride: false,
      reason: 'Shifts overlap. This worker is unavailable due to an overlapping shift.',
      gapMinutes: 0
    };
  }
  
  // Calculate gap between shifts
  let gapMinutes;
  if (s1End <= s2Start) {
    // Shift 1 ends before Shift 2 starts
    gapMinutes = s2Start - s1End;
  } else if (s2End <= s1Start) {
    // Shift 2 ends before Shift 1 starts
    gapMinutes = s1Start - s2End;
  } else {
    gapMinutes = 0;
  }
  
  // If gap is more than 1 hour (60 minutes), it's allowed without override
  if (gapMinutes > 60) {
    return {
      allowed: true,
      needsOverride: false,
      reason: '',
      gapMinutes
    };
  }
  
  // If gap is 1 hour or less, vendor can override (double shift scenario)
  return {
    allowed: false,
    needsOverride: true,
    reason: `This employee is finishing another shift within ${gapMinutes} minutes of this assignment. Vendor can override to assign a double shift.`,
    gapMinutes
  };
};

/**
 * Validates if a worker can be assigned to a shift
 * Returns: { valid: boolean, conflict: object | null, message: string }
 */
export const validateWorkerAssignment = (workerId, targetEvent, targetShift, allEvents, userRole) => {
  // Get all assignments for this worker on the target date
  const existingAssignments = getWorkerAssignments(workerId, allEvents, targetEvent.date);
  
  // If no existing assignments, allow
  if (existingAssignments.length === 0) {
    return { valid: true, conflict: null, message: '' };
  }
  
  // Check conflicts with each existing assignment
  for (const existingEvent of existingAssignments) {
    // Skip if it's the same event (editing existing assignment)
    if (existingEvent.id === targetEvent.id) continue;
    
    // Check each shift in the existing event
    for (const existingShift of (existingEvent.shifts || [])) {
      const conflict = checkShiftConflict(existingShift, targetShift);
      
      if (!conflict.allowed) {
        if (conflict.needsOverride) {
          // Vendor can override for double shifts within 1 hour
          if (userRole === 'vendor') {
            return {
              valid: false,
              conflict: {
                ...conflict,
                existingEvent,
                existingShift,
                canOverride: true
              },
              message: conflict.reason
            };
          } else {
            // Non-vendors cannot override
            return {
              valid: false,
              conflict: {
                ...conflict,
                existingEvent,
                existingShift,
                canOverride: false
              },
              message: 'This worker is unavailable due to an overlapping shift or extended gap. Assigning this employee is not permitted.'
            };
          }
        } else {
          // Hard conflict - no override allowed
          return {
            valid: false,
            conflict: {
              ...conflict,
              existingEvent,
              existingShift,
              canOverride: false
            },
            message: 'This worker is unavailable due to an overlapping shift or extended gap. Assigning this employee is not permitted.'
          };
        }
      }
    }
  }
  
  return { valid: true, conflict: null, message: '' };
};