# Complete DOCPLEX implementation

from docplex.mp.model import Model

def optimize_customer_complaints():
    """Optimize the allocation of staff to manage customer complaints."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="customer_complaints")
    
    # Data from the database
    resolution_times = [2, 3, 3]  # From Complaints table
    max_complaints = [5, 7, 6]    # From StaffCapacity table
    
    n_complaints = len(resolution_times)
    n_staff = len(max_complaints)
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(resolution_times) == n_complaints, "Resolution times length mismatch"
    assert len(max_complaints) == n_staff, "Max complaints length mismatch"
    
    # Safe range for indexing
    safe_complaints_range = range(n_complaints)
    safe_staff_range = range(n_staff)
    
    # 2. VARIABLES
    # Binary decision variables: x[i][j] = 1 if complaint i is assigned to staff j
    x = {(i, j): mdl.binary_var(name=f"x_{i}_{j}") for i in safe_complaints_range for j in safe_staff_range}
    
    # 3. OBJECTIVE FUNCTION
    # Minimize the total resolution time
    objective = mdl.sum(resolution_times[i] * x[i, j] for i in safe_complaints_range for j in safe_staff_range)
    mdl.minimize(objective)
    
    # 4. CONSTRAINTS
    
    # Each complaint must be assigned to exactly one staff member
    for i in safe_complaints_range:
        mdl.add_constraint(mdl.sum(x[i, j] for j in safe_staff_range) == 1, ctname=f"assign_complaint_{i}")
    
    # The number of complaints assigned to each staff member must not exceed their capacity
    for j in safe_staff_range:
        mdl.add_constraint(mdl.sum(x[i, j] for i in safe_complaints_range) <= max_complaints[j], ctname=f"staff_capacity_{j}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_complaints_range:
            for j in safe_staff_range:
                if solution.get_value(x[i, j]) > 1e-6:
                    print(f"Complaint {i} assigned to Staff {j}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")

    return mdl

# Run the optimization
optimize_customer_complaints()