# edited by glg
from pypos.core.utils.config_utils import read_config
from pypos.modules.dashboard.services.dashboard_value_utils import DashboardValueUtils
from pypos.modules.sinkronisasi.services.event_first_export_runtime_service import (
    EventFirstExportRuntimeService,
)
from pypos.modules.sinkronisasi.services.event_ingestion_gateway_service import (
    EventIngestionGatewayService,
)
from pypos.modules.sinkronisasi.services.event_outbox_service import EventOutboxService


class DashboardEventRuntimeMixin:
    @staticmethod
    def _to_non_negative_int(value, default=0):
        return DashboardValueUtils.to_non_negative_int(value, default)

    def _build_event_backpressure_policy(self):
        cfg = read_config() or {}
        return {
            "pending_warn": self._to_non_negative_int(cfg.get("event_outbox_backpressure_pending_warn"), 2500),
            "pending_critical": self._to_non_negative_int(
                cfg.get("event_outbox_backpressure_pending_critical"),
                10000,
            ),
            "error_warn_pct": max(
                0.0,
                self._safe_float(cfg.get("event_outbox_backpressure_error_warn_pct"), 2.0),
            ),
            "error_critical_pct": max(
                0.0,
                self._safe_float(cfg.get("event_outbox_backpressure_error_critical_pct"), 8.0),
            ),
            "latency_warn_ms": max(
                0.0,
                self._safe_float(cfg.get("event_outbox_backpressure_latency_warn_ms"), 800.0),
            ),
            "latency_critical_ms": max(
                0.0,
                self._safe_float(cfg.get("event_outbox_backpressure_latency_critical_ms"), 2000.0),
            ),
            "default_batch": max(
                1,
                self._to_non_negative_int(cfg.get("event_outbox_backpressure_default_batch"), 250),
            ),
            "min_batch": max(
                1,
                self._to_non_negative_int(cfg.get("event_outbox_backpressure_min_batch"), 10),
            ),
        }

    def _is_event_backpressure_enabled(self):
        cfg = read_config() or {}
        return int(cfg.get("event_outbox_backpressure_enabled", 1) or 1) == 1

    def _is_event_outbox_runtime_enabled(self):
        cfg = read_config() or {}
        return int(cfg.get("event_outbox_runtime_enabled", 1) or 1) == 1

    def _is_event_ingestion_runtime_enabled(self):
        cfg = read_config() or {}
        return int(cfg.get("event_ingestion_runtime_enabled", 1) or 1) == 1

    def _get_event_outbox_service(self):
        current = getattr(self, "_event_outbox_service", None)
        if current is not None:
            return current
        if not self._is_event_backpressure_enabled() and not self._is_event_outbox_runtime_enabled():
            return None
        try:
            self._event_outbox_service = EventOutboxService()
        except (
            TypeError,
            ValueError,
            KeyError,
            AttributeError,
            RuntimeError,
            OSError,
            LookupError,
            ArithmeticError,
            ImportError,
        ) as exc:
            self.log_warning(f"[EVENT_OUTBOX] Gagal inisialisasi service: {exc}")
            self._event_outbox_service = None
        return self._event_outbox_service

    def _get_event_first_export_runtime_service(self):
        current = getattr(self, "_event_first_export_runtime_service", None)
        if current is not None:
            return current
        if not self._is_event_ingestion_runtime_enabled():
            return None
        outbox_service = self._get_event_outbox_service()
        if outbox_service is None:
            return None
        try:
            gateway_service = EventIngestionGatewayService(
                outbox_service=outbox_service,
                backpressure_service=self._event_backpressure_service,
            )
            self._event_first_export_runtime_service = EventFirstExportRuntimeService(
                gateway_service=gateway_service,
                outbox_service=outbox_service,
            )
        except (
            TypeError,
            ValueError,
            KeyError,
            AttributeError,
            RuntimeError,
            OSError,
            LookupError,
            ArithmeticError,
            ImportError,
        ) as exc:
            self.log_warning(f"[EVENT_FIRST] Gagal inisialisasi runtime service: {exc}")
            self._event_first_export_runtime_service = None
        return self._event_first_export_runtime_service

    def _get_event_runtime_numeric_policy(self):
        cfg = read_config() or {}
        return {
            "dedup_window_seconds": max(
                1,
                self._to_non_negative_int(cfg.get("event_ingestion_export_trigger_dedup_window_sec"), 5),
            ),
            "claim_limit": max(
                1,
                self._to_non_negative_int(cfg.get("event_outbox_runtime_claim_limit"), 100),
            ),
            "lease_seconds": max(
                10,
                self._to_non_negative_int(cfg.get("event_outbox_runtime_lease_seconds"), 60),
            ),
            "max_inflight": max(
                1,
                self._to_non_negative_int(cfg.get("event_outbox_runtime_max_inflight"), 1000),
            ),
            "retry_delay_seconds": max(
                5,
                self._to_non_negative_int(cfg.get("event_outbox_runtime_retry_delay_seconds"), 30),
            ),
            "purge_sent_days": max(
                1,
                self._to_non_negative_int(cfg.get("event_outbox_runtime_purge_sent_days"), 7),
            ),
            "purge_limit": max(
                1,
                self._to_non_negative_int(cfg.get("event_outbox_runtime_purge_limit"), 2000),
            ),
            "release_expired_each_cycle": self._to_non_negative_int(
                cfg.get("event_outbox_runtime_release_expired_each_cycle"),
                1,
            )
            == 1,
        }

    def _build_event_runtime_metrics_payload(self, source="timer"):
        queue_metrics = {}
        outbox_service = self._get_event_outbox_service()
        if outbox_service is not None and hasattr(outbox_service, "get_queue_metrics"):
            try:
                queue_metrics = outbox_service.get_queue_metrics() or {}
            except (
                TypeError,
                ValueError,
                KeyError,
                AttributeError,
                RuntimeError,
                OSError,
                LookupError,
                ArithmeticError,
                ImportError,
            ):
                queue_metrics = {}
        runtime_metrics = {}
        runtime_service = getattr(self, "_export_runtime_metrics", None)
        if runtime_service is not None and hasattr(runtime_service, "snapshot"):
            try:
                runtime_metrics = runtime_service.snapshot() or {}
            except (
                TypeError,
                ValueError,
                KeyError,
                AttributeError,
                RuntimeError,
                OSError,
                LookupError,
                ArithmeticError,
                ImportError,
            ):
                runtime_metrics = {}
        return {
            "pending": int(queue_metrics.get("pending", 0) or 0),
            "inflight": int(queue_metrics.get("inflight", 0) or 0),
            "error_rate_pct": float(runtime_metrics.get("error_rate_pct", 0.0) or 0.0),
            "avg_latency_ms": float(runtime_metrics.get("p95_latency_ms", 0.0) or 0.0),
            "sample_count": int(runtime_metrics.get("attempt_sample_count", 0) or 0),
            "source": str(source or "").strip(),
        }
