#!/usr/bin/env python3
"""
DOCplex implementation for phone production optimization problem
"""

from docplex.mp.model import Model

def phone_production_optimization():
    """Optimize phone production to minimize total cost while meeting hardware and accreditation requirements."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="phone_production_optimization")
    
    # Data from the problem
    chip_models = [
        {"id": 1, "cost": 50.0, "RAM_MiB": 2048, "ROM_MiB": 32768},
        {"id": 2, "cost": 75.0, "RAM_MiB": 4096, "ROM_MiB": 65536},
        {"id": 3, "cost": 100.0, "RAM_MiB": 8192, "ROM_MiB": 131072}
    ]
    
    screen_modes = [
        {"id": 1, "cost": 30.0, "Accreditation_level": 3},
        {"id": 2, "cost": 45.0, "Accreditation_level": 4},
        {"id": 3, "cost": 60.0, "Accreditation_level": 5}
    ]
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(chip_models) == 3 and len(screen_modes) == 3, "Array length mismatch"
    safe_range_chip = range(len(chip_models))
    safe_range_screen = range(len(screen_modes))
    
    # 2. VARIABLES
    # Decision variables: x_{i,j} = number of phones produced with chip model i and screen mode j
    x = {(i, j): mdl.continuous_var(name=f"x_{i}_{j}", lb=0) 
         for i in safe_range_chip for j in safe_range_screen}
    
    # 3. OBJECTIVE FUNCTION
    # Minimize total cost: sum_{i,j} (c_i + s_j) * x_{i,j}
    total_cost = mdl.sum((chip_models[i]["cost"] + screen_modes[j]["cost"]) * x[(i, j)] 
                         for i in safe_range_chip for j in safe_range_screen)
    mdl.minimize(total_cost)
    
    # 4. CONSTRAINTS
    
    # Total RAM Constraint: sum_{i,j} r_i * x_{i,j} >= 8000
    total_ram = mdl.sum(chip_models[i]["RAM_MiB"] * x[(i, j)] 
                        for i in safe_range_chip for j in safe_range_screen)
    mdl.add_constraint(total_ram >= 8000, ctname="total_ram")
    
    # Total ROM Constraint: sum_{i,j} o_i * x_{i,j} >= 128000
    total_rom = mdl.sum(chip_models[i]["ROM_MiB"] * x[(i, j)] 
                        for i in safe_range_chip for j in safe_range_screen)
    mdl.add_constraint(total_rom >= 128000, ctname="total_rom")
    
    # Total Accreditation Level Constraint: sum_{i,j} a_j * x_{i,j} >= 5
    total_accreditation = mdl.sum(screen_modes[j]["Accreditation_level"] * x[(i, j)] 
                                  for i in safe_range_chip for j in safe_range_screen)
    mdl.add_constraint(total_accreditation >= 5, ctname="total_accreditation")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_range_chip:
            for j in safe_range_screen:
                value = solution.get_value(x[(i, j)])
                if value > 1e-6:
                    print(f"x_{i}_{j} = {value:.3f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Execute the optimization
if __name__ == "__main__":
    phone_production_optimization()