"""Memory watermark and allocator purge utilities for long-running processes."""

from __future__ import annotations

import logging

logger = logging.getLogger(__name__)

_WATERMARK_GC_RATIO = 0.65
_WATERMARK_ABORT_RATIO = 0.90


def _force_allocator_purge() -> None:
    """Force mimalloc/glibc to return freed pages to the OS immediately.

    On Linux with mimalloc (LD_PRELOAD), this calls mi_collect(true) which
    forces immediate page decommit — more aggressive than MIMALLOC_PURGE_DELAY.
    Falls back to glibc malloc_trim(0) if mimalloc is not loaded.
    No-op on macOS (not needed for development).
    """
    import ctypes
    import sys

    if sys.platform != "linux":
        return

    # Try mimalloc first (loaded via LD_PRELOAD in systemd service)
    try:
        libmi = ctypes.CDLL("libmimalloc.so.2")
        libmi.mi_collect(ctypes.c_bool(True))  # force=true: immediate purge
    except OSError:
        pass
    else:
        return

    # Fallback: glibc malloc_trim (returns free pages at top of heap)
    try:
        libc = ctypes.CDLL("libc.so.6")
        libc.malloc_trim(0)
    except OSError:
        pass


def _check_memory_watermark(memory_max_bytes: int) -> str:
    """Dask-style tiered watermark for chunked gap repair (MEM-014).

    Compares current process RSS against the configured memory ceiling
    (typically from systemd MemoryMax) and returns an action tier.

    Parameters
    ----------
    memory_max_bytes : int
        Memory ceiling in bytes (e.g., from systemd MemoryMax).

    Returns
    -------
    str
        ``"ok"`` — RSS < 65% of ceiling, continue normally.
        ``"gc"`` — RSS 65-90% of ceiling, run gc.collect() then continue.
        ``"abort"`` — RSS >= 90% of ceiling, stop processing to avoid OOM.
    """
    from opendeviationbar.resource_guard import _get_process_rss_mb

    rss_bytes = _get_process_rss_mb() * 1024 * 1024
    ratio = rss_bytes / memory_max_bytes if memory_max_bytes > 0 else 0.0

    if ratio >= _WATERMARK_ABORT_RATIO:
        return "abort"
    if ratio >= _WATERMARK_GC_RATIO:
        return "gc"
    return "ok"
