# Complete GUROBIPY implementation - Retry Attempt 4

import gurobipy as gp
from gurobipy import GRB

def optimize_customer_complaints():
    # 1. MODEL & DATA SETUP
    model = gp.Model("customer_complaints")
    
    # Data from the database
    staff_wages = {1: 25.0, 2: 30.0, 3: 35.0}
    complaint_time_constraints = {
        1: {'min_time': 1.0, 'max_time': 3.0},
        2: {'min_time': 1.5, 'max_time': 4.0},
        3: {'min_time': 2.0, 'max_time': 5.0}
    }
    staff_working_hours = {1: 40.0, 2: 45.0, 3: 50.0}
    
    # Extract staff and complaint IDs
    staff_ids = list(staff_wages.keys())
    complaint_ids = list(complaint_time_constraints.keys())
    
    # CRITICAL: Validate array lengths before loops
    assert len(staff_ids) > 0, "No staff members found"
    assert len(complaint_ids) > 0, "No complaints found"
    
    # 2. VARIABLES
    # Decision variable: time spent by staff member i on complaint j
    x = model.addVars(staff_ids, complaint_ids, vtype=GRB.CONTINUOUS, name="x", lb=0)
    
    # 3. OBJECTIVE FUNCTION
    # Minimize the total cost of handling complaints
    model.setObjective(
        gp.quicksum(staff_wages[i] * x[i, j] for i in staff_ids for j in complaint_ids),
        GRB.MINIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Complaint Assignment Constraint: Each complaint must be fully assigned
    for j in complaint_ids:
        model.addConstr(
            gp.quicksum(x[i, j] for i in staff_ids) == 1,
            name=f"complaint_assignment_{j}"
        )
    
    # Time Bounds Constraint: Time spent must be within min and max time for each complaint
    for i in staff_ids:
        for j in complaint_ids:
            model.addConstr(
                x[i, j] >= complaint_time_constraints[j]['min_time'],
                name=f"min_time_{i}_{j}"
            )
            model.addConstr(
                x[i, j] <= complaint_time_constraints[j]['max_time'],
                name=f"max_time_{i}_{j}"
            )
    
    # Staff Working Hours Constraint: Total time spent by each staff member must not exceed max hours
    for i in staff_ids:
        model.addConstr(
            gp.quicksum(x[i, j] for j in complaint_ids) <= staff_working_hours[i],
            name=f"staff_hours_{i}"
        )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in staff_ids:
            for j in complaint_ids:
                if x[i, j].x > 1e-6:
                    print(f"x[{i},{j}] = {x[i, j].x:.3f}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

# Execute the optimization
optimize_customer_complaints()