#!/usr/bin/env python3
"""
Gurobipy Implementation for News Report Optimization Problem
"""

import gurobipy as gp
from gurobipy import GRB

def optimize_news_report():
    """Optimize the assignment of journalists to events to maximize coverage quality."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("news_report_optimization")
    
    # Data from the problem
    journalists = [
        {"Years_working": 5, "max_assignments": 3},
        {"Years_working": 10, "max_assignments": 4},
        {"Years_working": 15, "max_assignments": 5}
    ]
    
    events = [
        {"Event_Attendance": 100},
        {"Event_Attendance": 200},
        {"Event_Attendance": 300}
    ]
    
    n_journalists = len(journalists)
    n_events = len(events)
    
    # CRITICAL: Validate array lengths before loops
    assert n_journalists > 0 and n_events > 0, "Array length mismatch"
    
    # 2. VARIABLES
    # Binary decision variables: x[i][j] = 1 if journalist i is assigned to event j
    x = model.addVars(n_journalists, n_events, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    # Maximize total coverage quality
    model.setObjective(
        gp.quicksum(
            journalists[i]["Years_working"] * events[j]["Event_Attendance"] * x[i, j]
            for i in range(n_journalists)
            for j in range(n_events)
        ),
        GRB.MAXIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Event Coverage Requirement: Each event must be covered by at least one journalist
    for j in range(n_events):
        model.addConstr(
            gp.quicksum(x[i, j] for i in range(n_journalists)) >= 1,
            name=f"event_coverage_{j}"
        )
    
    # Journalist Assignment Limit: No journalist can be assigned to more than their max_assignments
    for i in range(n_journalists):
        model.addConstr(
            gp.quicksum(x[i, j] for j in range(n_events)) <= journalists[i]["max_assignments"],
            name=f"journalist_limit_{i}"
        )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for i in range(n_journalists):
            for j in range(n_events):
                if x[i, j].x > 0.5:  # Check if assignment is made
                    print(f"Journalist {i} assigned to Event {j}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

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