# Complete PYOMO implementation - Retry Attempt 4

import pyomo.environ as pyo
from pyomo.opt import SolverFactory

def tvshow_optimization():
    """TV Show Scheduling Optimization using Pyomo"""
    
    # 1. MODEL CREATION
    model = pyo.ConcreteModel()
    
    # 2. DATA SETUP
    # Data from the problem statement
    viewers_m = [2, 3, 1]
    air_time = [60, 90, 30]
    content_type = ['series', 'cartoon', 'series']
    demographic_target = [80000, 120000, 50000]
    
    total_available_time = [48, 72, 24]
    content_capacity = [20, 30, 10]
    minimum_demographic_target = 200000
    
    # CRITICAL: Validate array lengths before indexing
    n_shows = len(viewers_m)
    n_channels = len(total_available_time)
    assert len(air_time) == len(content_type) == len(demographic_target) == n_shows, "Array length mismatch"
    assert len(total_available_time) == len(content_capacity) == n_channels, "Channel array length mismatch"
    
    # 3. SETS
    model.I = pyo.RangeSet(1, n_shows)  # Shows
    model.J = pyo.RangeSet(1, n_channels)  # Channels
    
    # 4. PARAMETERS
    model.viewers_m = pyo.Param(model.I, initialize={i+1: viewers_m[i] for i in range(n_shows)})
    model.air_time = pyo.Param(model.I, initialize={i+1: air_time[i] for i in range(n_shows)})
    model.demographic_target = pyo.Param(model.I, initialize={i+1: demographic_target[i] for i in range(n_shows)})
    model.total_available_time = pyo.Param(model.J, initialize={j+1: total_available_time[j] for j in range(n_channels)})
    model.content_capacity = pyo.Param(model.J, initialize={j+1: content_capacity[j] for j in range(n_channels)})
    
    # 5. VARIABLES
    model.x = pyo.Var(model.I, within=pyo.Binary)
    
    # 6. OBJECTIVE FUNCTION
    def obj_rule(model):
        return sum(model.viewers_m[i] * model.x[i] for i in model.I)
    model.objective = pyo.Objective(rule=obj_rule, sense=pyo.maximize)
    
    # 7. CONSTRAINTS
    
    # Total Air Time Constraint for Each Channel
    def air_time_constraint_rule(model, j):
        return sum(model.air_time[i] * model.x[i] for i in model.I) <= model.total_available_time[j]
    model.air_time_constraint = pyo.Constraint(model.J, rule=air_time_constraint_rule)
    
    # Content Type Capacity Constraint for Each Channel
    def content_capacity_constraint_rule(model, j):
        return sum(model.x[i] for i in model.I if content_type[i-1] == 'series') <= model.content_capacity[j]
    model.content_capacity_constraint = pyo.Constraint(model.J, rule=content_capacity_constraint_rule)
    
    # Minimum Demographic Viewership Constraint
    def demographic_constraint_rule(model):
        return sum(model.demographic_target[i] * model.x[i] for i in model.I) >= minimum_demographic_target
    model.demographic_constraint = pyo.Constraint(rule=demographic_constraint_rule)
    
    # 8. SOLVING WITH GUROBI
    solver = SolverFactory('gurobi')
    
    # Solve the model
    results = solver.solve(model, tee=True)
    
    # 9. RESULT PROCESSING
    if results.solver.termination_condition == pyo.TerminationCondition.optimal:
        print("Optimal solution found!")
        print(f"Optimal value: {pyo.value(model.objective)}")
        
        # Extract variable values
        print("\nSelected shows:")
        for i in model.I:
            if pyo.value(model.x[i]) > 0.5:  # Binary variable, check if selected
                print(f"Show {i} selected")
        
    elif results.solver.termination_condition == pyo.TerminationCondition.infeasible:
        print("Problem is infeasible")
    elif results.solver.termination_condition == pyo.TerminationCondition.unbounded:
        print("Problem is unbounded")
    else:
        print(f"Solver terminated with condition: {results.solver.termination_condition}")
    
    return model

# Execute the optimization
tvshow_optimization()