#!/usr/bin/env python3
"""
DOCplex Implementation for Host City Selection Optimization
"""

from docplex.mp.model import Model

def optimize_host_cities():
    """Optimize the selection of host cities for matches."""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="host_city_selection")
    
    # Data from the problem description
    city_ids = [1, 2, 3]
    populations = [800000, 1200000, 600000]
    gdps = [75000.0, 110000.0, 60000.0]
    avg_temperatures = [22.0, 26.0, 20.0]
    hosting_costs = [120000.0, 180000.0, 100000.0]
    
    # Weights for the objective function
    weight_population = 0.4
    weight_gdp = 0.3
    weight_temperature = 0.3
    
    # Constraints
    max_matches_per_city = 2
    total_budget = 1000000.0
    total_matches_limit = 10
    
    # CRITICAL: Validate array lengths to prevent IndexError
    assert len(city_ids) == len(populations) == len(gdps) == len(avg_temperatures) == len(hosting_costs), "Array length mismatch"
    safe_range = range(min(len(city_ids), len(populations), len(gdps), len(avg_temperatures), len(hosting_costs)))  # Safe indexing
    
    # 2. VARIABLES
    # Decision variables: number of matches hosted in each city
    x = {i: mdl.integer_var(name=f"x_{city_ids[i]}", lb=0, ub=max_matches_per_city) for i in safe_range}
    
    # 3. OBJECTIVE FUNCTION
    # Calculate the benefit for each city
    benefits = [
        (weight_population * populations[i] + weight_gdp * gdps[i] + weight_temperature * avg_temperatures[i]) 
        for i in safe_range
    ]
    
    # Maximize the total benefit
    objective = mdl.sum(benefits[i] * x[i] for i in safe_range)
    mdl.maximize(objective)
    
    # 4. CONSTRAINTS
    
    # Total Matches Constraint
    total_matches = mdl.sum(x[i] for i in safe_range)
    mdl.add_constraint(total_matches <= total_matches_limit, ctname="total_matches_limit")
    
    # Budget Constraint
    total_cost = mdl.sum(hosting_costs[i] * x[i] for i in safe_range)
    mdl.add_constraint(total_cost <= total_budget, ctname="total_budget_limit")
    
    # Maximum Matches Per City Constraint (already enforced by variable bounds)
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for i in safe_range:
            value = solution.get_value(x[i])
            if value > 1e-6:
                print(f"Matches in city {city_ids[i]}: {value}")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

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