import React from "react";
import { base44 } from "@/api/base44Client";

/**
 * Smart Assignment Engine - Core Logic
 * Removes 85% of manual work with intelligent assignment algorithms
 */

// Calculate worker fatigue based on recent shifts
export const calculateFatigue = (staff, allEvents) => {
  const now = new Date();
  const last7Days = allEvents.filter(e => {
    const eventDate = new Date(e.date);
    const diffDays = (now - eventDate) / (1000 * 60 * 60 * 24);
    return diffDays >= 0 && diffDays <= 7 && 
           e.assigned_staff?.some(s => s.staff_id === staff.id);
  });
  
  const shiftsLast7Days = last7Days.length;
  // Fatigue score: 0 (fresh) to 100 (exhausted)
  return Math.min(shiftsLast7Days * 15, 100);
};

// Calculate proximity score (0-100, higher is closer)
export const calculateProximity = (staff, eventLocation) => {
  if (!staff.hub_location || !eventLocation) return 50;
  
  // Simple match-based proximity (in production, use geocoding)
  if (staff.hub_location.toLowerCase() === eventLocation.toLowerCase()) return 100;
  if (staff.hub_location.toLowerCase().includes(eventLocation.toLowerCase()) ||
      eventLocation.toLowerCase().includes(staff.hub_location.toLowerCase())) return 75;
  return 30;
};

// Calculate compliance score
export const calculateCompliance = (staff) => {
  const hasBackground = staff.background_check_status === 'cleared';
  const hasCertifications = staff.certifications?.length > 0;
  const isActive = staff.employment_type && staff.employment_type !== 'Medical Leave';
  
  let score = 0;
  if (hasBackground) score += 40;
  if (hasCertifications) score += 30;
  if (isActive) score += 30;
  
  return score;
};

// Calculate cost optimization score
export const calculateCostScore = (staff, role, vendorRates) => {
  // Find matching rate for this staff/role
  const rate = vendorRates.find(r => 
    r.vendor_id === staff.vendor_id && 
    r.role_name === role
  );
  
  if (!rate) return 50;
  
  // Lower cost = higher score (inverted)
  const avgMarket = rate.market_average || rate.client_rate;
  if (!avgMarket) return 50;
  
  const costRatio = rate.client_rate / avgMarket;
  return Math.max(0, Math.min(100, (1 - costRatio) * 100 + 50));
};

// Detect shift time overlaps
export const hasTimeOverlap = (shift1, shift2, bufferMinutes = 30) => {
  if (!shift1.start_time || !shift1.end_time || !shift2.start_time || !shift2.end_time) {
    return false;
  }
  
  const parseTime = (timeStr) => {
    const [time, period] = timeStr.split(' ');
    let [hours, minutes] = time.split(':').map(Number);
    if (period === 'PM' && hours !== 12) hours += 12;
    if (period === 'AM' && hours === 12) hours = 0;
    return hours * 60 + minutes;
  };
  
  const s1Start = parseTime(shift1.start_time);
  const s1End = parseTime(shift1.end_time);
  const s2Start = parseTime(shift2.start_time);
  const s2End = parseTime(shift2.end_time);
  
  return (s1Start < s2End + bufferMinutes) && (s2Start < s1End + bufferMinutes);
};

// Check for double bookings
export const checkDoubleBooking = (staff, event, allEvents) => {
  const eventDate = new Date(event.date);
  const eventShift = event.shifts?.[0];
  
  if (!eventShift) return false;
  
  const conflicts = allEvents.filter(e => {
    if (e.id === event.id) return false;
    
    const eDate = new Date(e.date);
    const sameDay = eDate.toDateString() === eventDate.toDateString();
    if (!sameDay) return false;
    
    const isAssigned = e.assigned_staff?.some(s => s.staff_id === staff.id);
    if (!isAssigned) return false;
    
    // Check time overlap
    const eShift = e.shifts?.[0];
    if (!eShift) return false;
    
    return hasTimeOverlap(eventShift.roles?.[0], eShift.roles?.[0]);
  });
  
  return conflicts.length > 0;
};

// Smart Assignment Algorithm
export const smartAssign = async (event, role, allStaff, allEvents, vendorRates, options = {}) => {
  const {
    prioritizeSkill = true,
    prioritizeReliability = true,
    prioritizeVendor = true,
    prioritizeFatigue = true,
    prioritizeCompliance = true,
    prioritizeProximity = true,
    prioritizeCost = false,
    preferredVendorId = null,
    clientPreferences = {},
    sectorStandards = {},
  } = options;
  
  // Filter eligible staff
  const eligible = allStaff.filter(staff => {
    // Skill match
    const hasSkill = staff.position === role.role || staff.position_2 === role.role;
    if (!hasSkill) return false;
    
    // Active status
    if (staff.employment_type === 'Medical Leave') return false;
    
    // Double booking check
    if (checkDoubleBooking(staff, event, allEvents)) return false;
    
    // Sector standards (if any)
    if (sectorStandards.minimumRating && (staff.rating || 0) < sectorStandards.minimumRating) {
      return false;
    }
    
    return true;
  });
  
  // Score each eligible staff member
  const scored = eligible.map(staff => {
    let totalScore = 0;
    let weights = 0;
    
    // Skill match (base score)
    const isPrimarySkill = staff.position === role.role;
    const skillScore = isPrimarySkill ? 100 : 75;
    if (prioritizeSkill) {
      totalScore += skillScore * 2;
      weights += 2;
    }
    
    // Reliability
    if (prioritizeReliability) {
      const reliabilityScore = staff.reliability_score || staff.shift_coverage_percentage || 85;
      totalScore += reliabilityScore * 1.5;
      weights += 1.5;
    }
    
    // Vendor priority
    if (prioritizeVendor && preferredVendorId) {
      const vendorMatch = staff.vendor_id === preferredVendorId ? 100 : 50;
      totalScore += vendorMatch * 1.5;
      weights += 1.5;
    }
    
    // Fatigue (lower is better)
    if (prioritizeFatigue) {
      const fatigueScore = 100 - calculateFatigue(staff, allEvents);
      totalScore += fatigueScore * 1;
      weights += 1;
    }
    
    // Compliance
    if (prioritizeCompliance) {
      const complianceScore = calculateCompliance(staff);
      totalScore += complianceScore * 1.2;
      weights += 1.2;
    }
    
    // Proximity
    if (prioritizeProximity) {
      const proximityScore = calculateProximity(staff, event.event_location || event.hub);
      totalScore += proximityScore * 1;
      weights += 1;
    }
    
    // Cost optimization
    if (prioritizeCost) {
      const costScore = calculateCostScore(staff, role.role, vendorRates);
      totalScore += costScore * 1;
      weights += 1;
    }
    
    // Client preferences
    if (clientPreferences.favoriteStaff?.includes(staff.id)) {
      totalScore += 100 * 1.5;
      weights += 1.5;
    }
    if (clientPreferences.blockedStaff?.includes(staff.id)) {
      totalScore = 0; // Exclude completely
    }
    
    const finalScore = weights > 0 ? totalScore / weights : 0;
    
    return {
      staff,
      score: finalScore,
      breakdown: {
        skill: skillScore,
        reliability: staff.reliability_score || 85,
        fatigue: 100 - calculateFatigue(staff, allEvents),
        compliance: calculateCompliance(staff),
        proximity: calculateProximity(staff, event.event_location || event.hub),
        cost: calculateCostScore(staff, role.role, vendorRates),
      }
    };
  });
  
  // Sort by score descending
  scored.sort((a, b) => b.score - a.score);
  
  return scored;
};

// Auto-fill open shifts
export const autoFillShifts = async (event, allStaff, allEvents, vendorRates, options) => {
  const shifts = event.shifts || [];
  const assignments = [];
  
  for (const shift of shifts) {
    for (const role of shift.roles || []) {
      const needed = (role.count || 0) - (role.assigned || 0);
      if (needed <= 0) continue;
      
      const scored = await smartAssign(event, role, allStaff, allEvents, vendorRates, options);
      const selected = scored.slice(0, needed);
      
      assignments.push(...selected.map(s => ({
        staff_id: s.staff.id,
        staff_name: s.staff.employee_name,
        email: s.staff.email,
        role: role.role,
        department: role.department,
        shift_name: shift.shift_name,
        score: s.score,
      })));
    }
  }
  
  return assignments;
};

export default {
  smartAssign,
  autoFillShifts,
  calculateFatigue,
  calculateProximity,
  calculateCompliance,
  calculateCostScore,
  hasTimeOverlap,
  checkDoubleBooking,
};