#!/usr/bin/env python3
"""
DOCplex implementation for cinema scheduling optimization problem
"""

from docplex.mp.model import Model

def cinema_scheduling_optimization():
    """Optimize cinema scheduling to maximize revenue"""
    
    # 1. MODEL & DATA SETUP
    mdl = Model(name="cinema_scheduling")
    
    # Data from the database
    prices = [12.99, 9.99, 7.99]  # Price per showing for each film
    show_times_per_day = [3, 2, 1]  # Show times per day for each film
    capacities = [150, 200, 100]  # Capacity of each cinema
    
    # Business configuration parameters
    max_showings_per_day = 12  # Maximum showings per day per cinema
    min_showings_per_film = 1  # Minimum showings per film per cinema per day
    
    # CRITICAL: Validate array lengths to prevent IndexError
    n_films = len(prices)
    n_cinemas = len(capacities)
    assert len(prices) == len(show_times_per_day) == n_films, "Film data length mismatch"
    assert len(capacities) == n_cinemas, "Cinema data length mismatch"
    
    # Safe indexing ranges
    film_range = range(n_films)
    cinema_range = range(n_cinemas)
    
    # 2. VARIABLES
    # Decision variable: x[f][c] = number of showings per day for film f in cinema c
    x = {(f, c): mdl.continuous_var(name=f"x_{f}_{c}", lb=min_showings_per_film) 
         for f in film_range for c in cinema_range}
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total revenue: sum over films and cinemas of (price * capacity * x)
    revenue = mdl.sum(prices[f] * capacities[c] * x[(f, c)] 
                      for f in film_range for c in cinema_range)
    mdl.maximize(revenue)
    
    # 4. CONSTRAINTS
    
    # Constraint 1: Maximum showings per day per cinema
    for c in cinema_range:
        total_showings = mdl.sum(x[(f, c)] for f in film_range)
        mdl.add_constraint(total_showings <= max_showings_per_day, 
                          ctname=f"max_showings_cinema_{c}")
    
    # Constraint 2: Total capacity per day
    for c in cinema_range:
        total_capacity = mdl.sum(capacities[c] * x[(f, c)] for f in film_range)
        mdl.add_constraint(total_capacity <= capacities[c] * max_showings_per_day, 
                          ctname=f"total_capacity_cinema_{c}")
    
    # Constraint 3: Minimum showings per film per cinema per day
    for f in film_range:
        for c in cinema_range:
            mdl.add_constraint(x[(f, c)] >= min_showings_per_film, 
                              ctname=f"min_showings_film_{f}_cinema_{c}")
    
    # 5. SOLVING & RESULTS
    solution = mdl.solve()
    
    if solution:
        print(f"Optimal value: {solution.objective_value}")
        for f in film_range:
            for c in cinema_range:
                value = solution.get_value(x[(f, c)])
                print(f"Film {f} in Cinema {c}: {value:.2f} showings")
    else:
        print("No solution found")
        print(f"Status: {mdl.solve_details.status}")
    
    return mdl

# Run the optimization
if __name__ == "__main__":
    cinema_scheduling_optimization()