# Complete GUROBIPY implementation

import gurobipy as gp
from gurobipy import GRB

def optimize_shop_membership():
    """Optimize budget allocation for maximizing member purchases across branches"""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("shop_membership")
    
    # Data from the problem context
    branches = [1, 2, 3]
    total_budget = 45000
    min_budget = 10000
    purchase_coefficients = {1: 60000, 2: 90000, 3: 80000}
    
    # CRITICAL: Validate array lengths before loops
    assert len(branches) == len(purchase_coefficients), "Array length mismatch"
    
    # 2. VARIABLES
    # Variable dictionaries for budget allocation
    budget_allocation = {branch: model.addVar(vtype=GRB.CONTINUOUS, name=f"x_{branch}", lb=0) 
                         for branch in branches}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total purchases
    model.setObjective(gp.quicksum(purchase_coefficients[branch] * budget_allocation[branch] 
                                   for branch in branches), GRB.MAXIMIZE)
    
    # 4. CONSTRAINTS - CORRECT SYNTAX PATTERNS
    
    # Total budget constraint
    model.addConstr(gp.quicksum(budget_allocation[branch] for branch in branches) <= total_budget, 
                    name="total_budget")
    
    # Minimum budget allocation for each branch
    for branch in branches:
        model.addConstr(budget_allocation[branch] >= min_budget, name=f"min_budget_{branch}")
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for branch in branches:
            if budget_allocation[branch].x > 1e-6:
                print(f"Budget allocation for branch {branch}: {budget_allocation[branch].x:.2f}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Run the optimization
optimize_shop_membership()