#!/usr/bin/env python3
"""
Gurobipy 12.0.2 Implementation for Flight Optimization Problem
"""

import gurobipy as gp
from gurobipy import GRB

def flight_optimization():
    """Optimize flight operations to minimize costs while ensuring operational efficiency."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("flight_optimization")
    
    # Example data (replace with actual data from database)
    flights = [101, 102, 103]
    employees = [1, 2, 3]
    origins = ['JFK', 'LAX', 'ORD']
    destinations = ['LAX', 'JFK', 'DFW']
    max_flights = {'JFK-LAX': 8, 'LAX-JFK': 8, 'ORD-DFW': 5}
    flight_costs = {101: 5000, 102: 6000, 103: 5500}
    employee_salaries = {1: 3000, 2: 3500, 3: 3200}
    
    # CRITICAL: Validate array lengths before loops
    assert len(flights) == len(flight_costs), "Flight data length mismatch"
    assert len(employees) == len(employee_salaries), "Employee data length mismatch"
    
    # 2. VARIABLES
    # Decision variables
    x = {f: model.addVar(vtype=GRB.BINARY, name=f"x_{f}") for f in flights}
    y = {(e, f): model.addVar(vtype=GRB.BINARY, name=f"y_{e}_{f}") for e in employees for f in flights}
    
    # 3. OBJECTIVE FUNCTION
    # Minimize total cost: sum of flight operational costs and employee salaries
    model.setObjective(
        gp.quicksum(flight_costs[f] * x[f] for f in flights) +
        gp.quicksum(employee_salaries[e] * y[e, f] for e in employees for f in flights),
        GRB.MINIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Flight Capacity Constraint
    for o in origins:
        for d in destinations:
            key = f"{o}-{d}"
            if key in max_flights:
                model.addConstr(
                    gp.quicksum(x[f] for f in flights if f in flight_costs) <= max_flights[key],
                    name=f"capacity_{o}_{d}"
                )
    
    # Employee Assignment Constraint
    for f in flights:
        model.addConstr(
            gp.quicksum(y[e, f] for e in employees) >= x[f],
            name=f"assignment_{f}"
        )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for f in flights:
            if x[f].x > 1e-6:
                print(f"Flight {f} is operated.")
        for e in employees:
            for f in flights:
                if y[e, f].x > 1e-6:
                    print(f"Employee {e} is assigned to flight {f}.")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
if __name__ == "__main__":
    flight_optimization()