use super::{BudgetPressure, SignalBudget};

#[derive(Debug, Clone)]
pub enum PolicyAction {
    Allow,
    SoftWarn(String),
    AutoTrim { keep_lines: usize },
    Reject(String),
}

pub struct BudgetPolicy {
    pub hard_cap: usize,
    pub warn_at_pct: f64,
    pub trim_at_pct: f64,
}

impl BudgetPolicy {
    pub fn default_policy() -> Self {
        Self {
            hard_cap: 8_000,
            warn_at_pct: 0.65,
            trim_at_pct: 0.85,
        }
    }

    pub fn evaluate(&self, budget: &SignalBudget, incoming_tokens: usize) -> PolicyAction {
        let projected = budget.used + incoming_tokens;
        let projected_pct = projected as f64 / self.hard_cap as f64;

        if projected > self.hard_cap {
            return PolicyAction::Reject(format!(
                "budget overflow: {projected} > {}",
                self.hard_cap
            ));
        }

        match budget.pressure() {
            BudgetPressure::Overflow | BudgetPressure::Critical => {
                let keep = (self.hard_cap.saturating_sub(budget.used)) / 4;
                PolicyAction::AutoTrim {
                    keep_lines: keep.max(5),
                }
            }
            BudgetPressure::Elevated => {
                PolicyAction::SoftWarn(format!("context at {:.0}% capacity", projected_pct * 100.0))
            }
            BudgetPressure::Calm => PolicyAction::Allow,
        }
    }
}
