# Complete DOCPLEX implementation - Retry Attempt 4

from docplex.mp.model import Model

def machine_repair_optimization():
    # 1. MODEL & DATA SETUP
    mdl = Model(name="machine_repair_optimization")
    
    # Data from the database
    repair_time_data = {
        (1, 101): 2.5,
        (2, 102): 3.0,
        (3, 103): 4.0
    }
    
    technician_capacity_data = {
        1: 5,
        2: 4,
        3: 3
    }
    
    machine_priority_data = {
        101: 1,
        102: 2,
        103: 3
    }
    
    # Extract unique technicians and repairs
    technicians = list(technician_capacity_data.keys())
    repairs = list(machine_priority_data.keys())
    
    # CRITICAL: Validate array lengths and data completeness
    assert all((i, j) in repair_time_data for i in technicians for j in repairs), "Missing repair time data"
    
    # 2. VARIABLES
    x = {(i, j): mdl.binary_var(name=f"x_{i}_{j}") for i in technicians for j in repairs}
    
    # 3. OBJECTIVE FUNCTION
    objective = mdl.sum(repair_time_data[(i, j)] * x[(i, j)] for i in technicians for j in repairs)
    mdl.minimize(objective)
    
    # 4. CONSTRAINTS
    
    # Single Assignment per Repair
    for j in repairs:
        mdl.add_constraint(mdl.sum(x[(i, j)] for i in technicians) == 1, ctname=f"single_assignment_{j}")
    
    # Technician Capacity Limit
    for i in technicians:
        mdl.add_constraint(mdl.sum(x[(i, j)] for j in repairs) <= technician_capacity_data[i], ctname=f"capacity_{i}")
    
    # Priority Level Requirement (implicitly handled by objective and single assignment)
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in technicians:
            for j in repairs:
                if solution.get_value(x[(i, j)]) > 0:
                    print(f"Technician {i} assigned to Repair {j}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Execute the optimization
machine_repair_optimization()