/**
 * Overtime & Double Time Calculator
 * Calculates OT/DT exposure based on state regulations
 */

// State-specific OT/DT rules
const STATE_RULES = {
  CA: {
    dailyOT: 8,      // OT after 8 hours/day
    dailyDT: 12,     // DT after 12 hours/day
    weeklyOT: 40,    // OT after 40 hours/week
    seventhDayDT: true, // 7th consecutive day = DT
    otRate: 1.5,
    dtRate: 2.0,
  },
  DEFAULT: {
    dailyOT: null,   // No daily OT in most states
    dailyDT: null,
    weeklyOT: 40,
    seventhDayDT: false,
    otRate: 1.5,
    dtRate: 2.0,
  }
};

export function getStateRules(state) {
  return STATE_RULES[state] || STATE_RULES.DEFAULT;
}

/**
 * Calculate OT status for a worker considering a shift
 * @param {Object} worker - Worker with current hours
 * @param {Object} shift - Shift to assign
 * @param {Array} allEvents - All events to check existing assignments
 * @returns {Object} OT analysis
 */
export function calculateOTStatus(worker, shift, allEvents = []) {
  const state = shift.state || worker.state || "DEFAULT";
  const rules = getStateRules(state);
  
  // Get shift duration
  const shiftHours = calculateShiftHours(shift);
  
  // Calculate current hours from existing assignments
  const currentHours = calculateWorkerCurrentHours(worker, allEvents, shift.date);
  
  // Project new hours
  const projectedDayHours = currentHours.currentDayHours + shiftHours;
  const projectedWeekHours = currentHours.currentWeekHours + shiftHours;
  
  // Calculate OT/DT
  let otHours = 0;
  let dtHours = 0;
  let status = "GREEN";
  let summary = "No OT or DT triggered";
  let costImpact = 0;
  
  // Daily OT/DT (CA-specific)
  if (rules.dailyOT && projectedDayHours > rules.dailyOT) {
    if (rules.dailyDT && projectedDayHours > rules.dailyDT) {
      // Some hours are DT
      dtHours = projectedDayHours - rules.dailyDT;
      otHours = rules.dailyDT - rules.dailyOT;
      status = "RED";
      summary = `Triggers ${otHours.toFixed(1)}h OT + ${dtHours.toFixed(1)}h DT (${state})`;
    } else {
      // Only OT, no DT
      otHours = projectedDayHours - rules.dailyOT;
      status = projectedDayHours >= rules.dailyDT - 1 ? "AMBER" : "AMBER";
      summary = `Triggers ${otHours.toFixed(1)}h OT (${state})`;
    }
  }
  
  // Weekly OT
  if (rules.weeklyOT && projectedWeekHours > rules.weeklyOT && !otHours) {
    otHours = projectedWeekHours - rules.weeklyOT;
    status = "AMBER";
    summary = `Triggers ${otHours.toFixed(1)}h weekly OT`;
  }
  
  // Near thresholds (warning zone)
  if (status === "GREEN") {
    if (rules.dailyOT && projectedDayHours >= rules.dailyOT - 1) {
      status = "AMBER";
      summary = `Near daily OT threshold (${projectedDayHours.toFixed(1)}h)`;
    } else if (rules.weeklyOT && projectedWeekHours >= rules.weeklyOT - 4) {
      status = "AMBER";
      summary = `Approaching weekly OT (${projectedWeekHours.toFixed(1)}h)`;
    } else {
      summary = `Safe · No OT (${projectedDayHours.toFixed(1)}h day, ${projectedWeekHours.toFixed(1)}h week)`;
    }
  }
  
  // Calculate cost impact
  const baseRate = worker.hourly_rate || shift.rate_per_hour || 20;
  const baseCost = shiftHours * baseRate;
  const otCost = otHours * baseRate * rules.otRate;
  const dtCost = dtHours * baseRate * rules.dtRate;
  costImpact = otCost + dtCost;
  
  return {
    status,
    summary,
    currentDayHours: currentHours.currentDayHours,
    currentWeekHours: currentHours.currentWeekHours,
    projectedDayHours,
    projectedWeekHours,
    otHours,
    dtHours,
    baseCost,
    costImpact,
    totalCost: baseCost + costImpact,
    rulePattern: `${state}_${rules.dailyOT ? 'DAILY' : 'WEEKLY'}_OT`,
    canAssign: true, // Always allow but warn
    requiresApproval: status === "RED",
  };
}

/**
 * Calculate shift duration in hours
 */
function calculateShiftHours(shift) {
  if (shift.hours) return shift.hours;
  
  // Try to parse from start/end times
  if (shift.start_time && shift.end_time) {
    const [startH, startM] = shift.start_time.split(':').map(Number);
    const [endH, endM] = shift.end_time.split(':').map(Number);
    const startMins = startH * 60 + startM;
    const endMins = endH * 60 + endM;
    const duration = (endMins - startMins) / 60;
    return duration > 0 ? duration : duration + 24; // Handle overnight
  }
  
  return 8; // Default 8-hour shift
}

/**
 * Calculate worker's current hours for the day and week
 */
function calculateWorkerCurrentHours(worker, allEvents, shiftDate) {
  let currentDayHours = 0;
  let currentWeekHours = 0;
  
  if (!allEvents || !shiftDate) {
    return {
      currentDayHours: worker.current_day_hours || 0,
      currentWeekHours: worker.current_week_hours || 0,
    };
  }
  
  const shiftDateObj = new Date(shiftDate);
  const shiftDay = shiftDateObj.getDay();
  
  // Get start of week (Sunday)
  const weekStart = new Date(shiftDateObj);
  weekStart.setDate(shiftDateObj.getDate() - shiftDay);
  weekStart.setHours(0, 0, 0, 0);
  
  // Count hours from existing assignments
  allEvents.forEach(event => {
    if (event.status === "Canceled" || event.status === "Completed") return;
    
    const isAssigned = event.assigned_staff?.some(s => s.staff_id === worker.id);
    if (!isAssigned) return;
    
    const eventDate = new Date(event.date);
    
    // Same day hours
    if (eventDate.toDateString() === shiftDateObj.toDateString()) {
      (event.shifts || []).forEach(shift => {
        (shift.roles || []).forEach(role => {
          if (event.assigned_staff?.some(s => s.staff_id === worker.id && s.role === role.role)) {
            currentDayHours += role.hours || 8;
          }
        });
      });
    }
    
    // Same week hours
    if (eventDate >= weekStart && eventDate <= shiftDateObj) {
      (event.shifts || []).forEach(shift => {
        (shift.roles || []).forEach(role => {
          if (event.assigned_staff?.some(s => s.staff_id === worker.id && s.role === role.role)) {
            currentWeekHours += role.hours || 8;
          }
        });
      });
    }
  });
  
  return { currentDayHours, currentWeekHours };
}

/**
 * Get OT badge component props
 */
export function getOTBadgeProps(status) {
  switch (status) {
    case "GREEN":
      return {
        className: "bg-emerald-500 text-white",
        label: "Safe · No OT"
      };
    case "AMBER":
      return {
        className: "bg-amber-500 text-white",
        label: "Near OT"
      };
    case "RED":
      return {
        className: "bg-red-500 text-white",
        label: "OT/DT Risk"
      };
    default:
      return {
        className: "bg-slate-500 text-white",
        label: "Unknown"
      };
  }
}