#!/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 adhering to airport capacities."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("flight_optimization")
    
    # Data from the problem context
    routes = ['NYC-LAX', 'CHI-MIA', 'SEA-DEN']
    costs = {'NYC-LAX': 4500, 'CHI-MIA': 3500, 'SEA-DEN': 3000}
    airport_capacities = {'JFK': 150, 'ORD': 120, 'SEA': 80}
    
    # CRITICAL: Validate array lengths before loops
    assert len(routes) == len(costs), "Route and cost array length mismatch"
    
    # 2. VARIABLES
    # Decision variables: number of flights on each route
    x = {r: model.addVar(vtype=GRB.INTEGER, name=f"x_{r}", lb=1) for r in routes}
    
    # 3. OBJECTIVE FUNCTION
    # Minimize the total cost of operating all flights
    model.setObjective(gp.quicksum(costs[r] * x[r] for r in routes), GRB.MINIMIZE)
    
    # 4. CONSTRAINTS
    
    # Route Coverage: Each route must be covered by at least one flight
    for r in routes:
        model.addConstr(x[r] >= 1, name=f"route_coverage_{r}")
    
    # Airport Departure Capacity: Total flights departing from any airport must not exceed its capacity
    # Assuming NYC-LAX departs from JFK, CHI-MIA from ORD, SEA-DEN from SEA
    model.addConstr(x['NYC-LAX'] <= airport_capacities['JFK'], name="departure_capacity_JFK")
    model.addConstr(x['CHI-MIA'] <= airport_capacities['ORD'], name="departure_capacity_ORD")
    model.addConstr(x['SEA-DEN'] <= airport_capacities['SEA'], name="departure_capacity_SEA")
    
    # Airport Arrival Capacity: Total flights arriving at any airport must not exceed its capacity
    # Assuming NYC-LAX arrives at LAX, CHI-MIA at MIA, SEA-DEN at DEN
    # Since LAX, MIA, and DEN capacities are not provided, we assume they are sufficiently large
    # If capacities were provided, constraints would be added similarly to departure capacities
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for r in routes:
            print(f"Flights on {r}: {x[r].x}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

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