# Complete DOCPLEX implementation

from docplex.mp.model import Model

def optimize_store_product_distribution():
    """Optimize product distribution to maximize sales potential across stores."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="store_product")
    
    # Data from the database schema
    product_sales_value = {1: 12.5, 2: 25.0, 3: 18.0}
    product_availability = {1: 60, 2: 80, 3: 70}
    store_capacity = {1: 120, 2: 180, 3: 150}
    
    # Extract keys for safe indexing
    products = list(product_sales_value.keys())
    stores = list(store_capacity.keys())
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(product_sales_value) == len(product_availability) == len(products), "Product array length mismatch"
    assert len(store_capacity) == len(stores), "Store array length mismatch"
    
    # 2. VARIABLES
    # Decision variables: units assigned to each product in each store
    units_assigned = {(i, j): mdl.integer_var(name=f"x_{i}_{j}", lb=0) for i in products for j in stores}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total sales value
    objective = mdl.sum(product_sales_value[i] * units_assigned[i, j] for i in products for j in stores)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Product Availability Constraint
    for i in products:
        mdl.add_constraint(mdl.sum(units_assigned[i, j] for j in stores) <= product_availability[i], ctname=f"availability_{i}")
    
    # Store Capacity Constraint
    for j in stores:
        mdl.add_constraint(mdl.sum(units_assigned[i, j] for i in products) <= store_capacity[j], ctname=f"capacity_{j}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in products:
            for j in stores:
                value = solution.get_value(units_assigned[i, j])
                if value > 1e-6:
                    print(f"Units assigned to product {i} in store {j}: {value:.0f}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Run the optimization
optimize_store_product_distribution()