# Complete GUROBIPY implementation

import gurobipy as gp
from gurobipy import GRB

def optimize_phone_distribution():
    """Optimize phone stock distribution to maximize revenue."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("phone_market")
    
    # Data from the database
    markets = [1, 2, 3]
    phones = [101, 102, 103]
    available_stock = {101: 150, 102: 200, 103: 100}
    prices = {101: 299.99, 102: 399.99, 103: 499.99}
    max_stock_capacity = {1: 100, 2: 150, 3: 80}  # Assumed values for demonstration
    
    # CRITICAL: Validate array lengths before loops
    assert len(available_stock) == len(prices) == len(phones), "Array length mismatch"
    
    # 2. VARIABLES
    # Decision variables: number of phones allocated to each market
    x = model.addVars(markets, phones, vtype=GRB.INTEGER, name="Num_of_stock", lb=0)
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total revenue
    model.setObjective(gp.quicksum(prices[p] * x[m, p] for m in markets for p in phones), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS
    
    # Stock Availability Constraint
    model.addConstrs((gp.quicksum(x[m, p] for m in markets) <= available_stock[p] for p in phones), name="stock_availability")
    
    # Market Capacity Constraint
    model.addConstrs((gp.quicksum(x[m, p] for p in phones) <= max_stock_capacity[m] for m in markets), name="market_capacity")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for m in markets:
            for p in phones:
                if x[m, p].x > 1e-6:
                    print(f"Num_of_stock[{m},{p}] = {x[m, p].x:.0f}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
optimize_phone_distribution()