"""Async policy worker helpers for periodic policy evaluation."""

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime
from threading import Event, Thread
from typing import Any, Callable, Iterable, Optional

from hieromem_core.policy.evaluator import MemoryPolicyEvaluator


@dataclass
class PolicySweepResult:
    evaluated_at: datetime
    candidates: int
    forgotten: int


class PolicyWorker:
    """Lightweight policy sweep runner (async integration happens elsewhere)."""

    def __init__(
        self,
        evaluator: MemoryPolicyEvaluator,
        forget_callback: Callable[[Iterable[Any]], int],
    ) -> None:
        self.evaluator = evaluator
        self.forget_callback = forget_callback

    def run_retention_sweep(self, episodes: Iterable[Any]) -> PolicySweepResult:
        candidates = self.evaluator.retention_candidates(episodes)
        forgotten = self.forget_callback(candidates)
        return PolicySweepResult(
            evaluated_at=datetime.now(),
            candidates=len(candidates),
            forgotten=forgotten,
        )


class PolicyScheduler:
    """Periodically run retention sweeps in a background thread."""

    def __init__(
        self,
        worker: PolicyWorker,
        *,
        interval_s: float = 3600.0,
    ) -> None:
        self.worker = worker
        self.interval_s = interval_s
        self._stop_event = Event()
        self._thread: Optional[Thread] = None

    def start(self, episodes_provider: Callable[[], Iterable[Any]]) -> None:
        if self._thread and self._thread.is_alive():
            return

        def _loop() -> None:
            while not self._stop_event.is_set():
                episodes = list(episodes_provider())
                self.worker.run_retention_sweep(episodes)
                self._stop_event.wait(self.interval_s)

        self._stop_event.clear()
        self._thread = Thread(target=_loop, daemon=True)
        self._thread.start()

    def stop(self) -> None:
        self._stop_event.set()
        if self._thread:
            self._thread.join(timeout=2.0)
