#!/usr/bin/env python3
"""
Gurobipy 12.0.2 Implementation for Document Template Management Optimization
"""

import gurobipy as gp
from gurobipy import GRB

def optimize_template_allocation():
    """Optimize the allocation of document templates to minimize total cost."""
    
    # 1. MODEL & DATA SETUP
    model = gp.Model("template_allocation")
    
    # Data from the database
    template_ids = [1, 2, 3]
    document_ids = [101, 102, 103]
    
    # Template costs
    template_costs = {
        1: 12.5,
        2: 18.0,
        3: 10.0
    }
    
    # Template validity
    template_validity = {
        1: 1,
        2: 0,
        3: 1
    }
    
    # CRITICAL: Validate array lengths before loops
    assert len(template_ids) == len(template_costs) == len(template_validity), "Template data length mismatch"
    
    # 2. VARIABLES
    # Decision variables: x[t, d] = 1 if template t is used for document d, else 0
    x = model.addVars(template_ids, document_ids, vtype=GRB.BINARY, name="x")
    
    # 3. OBJECTIVE FUNCTION
    # Minimize the total cost of document creation
    model.setObjective(
        gp.quicksum(template_costs[t] * x[t, d] for t in template_ids for d in document_ids),
        GRB.MINIMIZE
    )
    
    # 4. CONSTRAINTS
    
    # Constraint 1: Single Template per Document
    for d in document_ids:
        model.addConstr(
            gp.quicksum(x[t, d] for t in template_ids) == 1,
            name=f"single_template_{d}"
        )
    
    # Constraint 2: Template Validity
    for t in template_ids:
        for d in document_ids:
            model.addConstr(
                x[t, d] <= template_validity[t],
                name=f"validity_{t}_{d}"
            )
    
    # 5. SOLVING & RESULTS
    model.optimize()
    
    if model.status == GRB.OPTIMAL:
        print(f"Optimal value: {model.objVal}")
        for t in template_ids:
            for d in document_ids:
                if x[t, d].x > 0.5:
                    print(f"Template {t} is used for document {d}")
    elif model.status == GRB.INFEASIBLE:
        print("Problem is infeasible")
    elif model.status == GRB.UNBOUNDED:
        print("Problem is unbounded")
    
    return model

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