# Complete GUROBIPY implementation - Retry Attempt 4

import gurobipy as gp
from gurobipy import GRB

def flight_company_optimization():
    """Optimize flight assignments to minimize operational costs."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("flight_company")
    
    # Example data setup (replace with actual data retrieval logic)
    flight_ids = [1, 2, 3]
    airport_ids = [101, 102, 103]
    
    distances = {
        (1, 101): 550.0,
        (2, 102): 800.0,
        (3, 103): 950.0
    }
    
    fee_rates = {
        101: 12.0,
        102: 18.0,
        103: 22.0
    }
    
    capacities = {
        101: 120,
        102: 180,
        103: 150
    }
    
    # CRITICAL: Validate data lengths
    assert len(flight_ids) * len(airport_ids) == len(distances), "Data length mismatch"
    
    # 2. VARIABLES
    x = model.addVars(flight_ids, airport_ids, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    model.setObjective(
        gp.quicksum(distances[i, j] * fee_rates[j] * x[i, j] for i in flight_ids for j in airport_ids),
        GRB.MINIMIZE
    )
    
    # 4. CONSTRAINTS
    # Each flight must be assigned to exactly one airport
    model.addConstrs(
        (gp.quicksum(x[i, j] for j in airport_ids) == 1 for i in flight_ids),
        name="assign_flight"
    )
    
    # The total number of flights assigned to an airport must not exceed its capacity
    model.addConstrs(
        (gp.quicksum(x[i, j] for i in flight_ids) <= capacities[j] for j in airport_ids),
        name="capacity_limit"
    )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in flight_ids:
            for j in airport_ids:
                if x[i, j].x > 1e-6:
                    print(f"Flight {i} assigned to Airport {j}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    else:
        print("Optimization ended with status", model.status)

# Run the optimization
flight_company_optimization()