from typing import Dict

# edited by glg


class EventIngestionBackpressureService:
    def __init__(self, config: Dict = None):
        cfg = dict(config or {})
        self.pending_warn = int(cfg.get("pending_warn", 2500) or 2500)
        self.pending_critical = int(cfg.get("pending_critical", 10000) or 10000)
        self.error_warn_pct = float(cfg.get("error_warn_pct", 2.0) or 2.0)
        self.error_critical_pct = float(cfg.get("error_critical_pct", 8.0) or 8.0)
        self.latency_warn_ms = float(cfg.get("latency_warn_ms", 800.0) or 800.0)
        self.latency_critical_ms = float(cfg.get("latency_critical_ms", 2000.0) or 2000.0)
        self.default_batch = int(cfg.get("default_batch", 250) or 250)
        # edited by glg
        # Floor batch tidak lagi hardcoded 50.
        # Node lemah bisa menurunkan agresivitas ingest lewat min_batch.
        self.min_batch = max(1, int(cfg.get("min_batch", 10) or 10))

    def evaluate(self, metrics: Dict) -> Dict:
        data = dict(metrics or {})
        pending = int(data.get("pending", 0) or 0)
        inflight = int(data.get("inflight", 0) or 0)
        error_pct = float(data.get("error_rate_pct", 0.0) or 0.0)
        latency_ms = float(data.get("avg_latency_ms", 0.0) or 0.0)

        mode = "normal"
        ingest_enabled = True
        reason = "healthy"
        max_batch = max(int(self.min_batch), int(self.default_batch))
        poll_delay_ms = 200

        if (
            pending >= self.pending_critical
            or error_pct >= self.error_critical_pct
            or latency_ms >= self.latency_critical_ms
        ):
            mode = "critical"
            ingest_enabled = False
            reason = "critical_threshold_reached"
            max_batch = int(self.min_batch)
            poll_delay_ms = 2500
        elif (
            pending >= self.pending_warn
            or error_pct >= self.error_warn_pct
            or latency_ms >= self.latency_warn_ms
        ):
            mode = "throttle"
            ingest_enabled = True
            reason = "warn_threshold_reached"
            max_batch = min(max_batch, max(int(self.min_batch), 100))
            poll_delay_ms = 1200
        elif inflight > 0:
            mode = "normal_inflight"
            max_batch = min(max_batch, max(int(self.min_batch), 180))
            poll_delay_ms = 350

        return {
            "mode": mode,
            "ingest_enabled": bool(ingest_enabled),
            "reason": reason,
            "recommended_batch_size": int(max_batch),
            "recommended_poll_delay_ms": int(max(100, poll_delay_ms)),
            "snapshot": {
                "pending": pending,
                "inflight": inflight,
                "error_rate_pct": error_pct,
                "avg_latency_ms": latency_ms,
            },
        }
