"""In-memory terminal delivery replay store keyed by ws_id.

Holds a copy of the last terminal payload per ws_id until TTL eviction.
Author: Vasiliy Zdanovskiy
email: vasilyvz@gmail.com
"""

from __future__ import annotations

import asyncio
import copy
import time
from typing import Dict, Optional

DEFAULT_REPLAY_TTL_SECONDS = 3600.0
DEFAULT_MAX_ENTRIES = 10000


def _normalize_ws_id(ws_id: str) -> str:
    """Return stripped ws_id; caller checks for empty."""
    return str(ws_id).strip()


class TerminalReplayStore:
    """In-memory map ws_id -> terminal payload with TTL and max entries."""

    def __init__(
        self,
        ttl_seconds: float | None = None,
        max_entries: int | None = None,
    ) -> None:
        self._lock = asyncio.Lock()
        self._data: Dict[str, dict] = {}
        self._created_monotonic: Dict[str, float] = {}
        self._ttl_seconds = (
            DEFAULT_REPLAY_TTL_SECONDS if ttl_seconds is None else float(ttl_seconds)
        )
        self._max_entries = (
            DEFAULT_MAX_ENTRIES if max_entries is None else int(max_entries)
        )

    def _is_expired_locked(self, ws_id: str) -> bool:
        ts = self._created_monotonic.get(ws_id)
        if ts is None:
            return True
        return (time.monotonic() - ts) > self._ttl_seconds

    def _evict_expired_locked(self) -> None:
        to_remove = [k for k in self._data if self._is_expired_locked(k)]
        for k in to_remove:
            self._data.pop(k, None)
            self._created_monotonic.pop(k, None)

    def _evict_one_oldest_locked(self) -> None:
        if len(self._data) <= self._max_entries:
            return
        if not self._created_monotonic:
            return
        oldest_key = min(
            self._created_monotonic.keys(),
            key=lambda k: (self._created_monotonic[k], k),
        )
        self._data.pop(oldest_key, None)
        self._created_monotonic.pop(oldest_key, None)

    async def store_terminal(self, ws_id: str, payload: dict) -> None:
        """Last-writer wins: deep-copy payload into store; set monotonic now."""
        wid = _normalize_ws_id(ws_id)
        if wid == "":
            return
        async with self._lock:
            self._evict_expired_locked()
            self._data[wid] = copy.deepcopy(payload)
            self._created_monotonic[wid] = time.monotonic()
            self._evict_one_oldest_locked()

    async def get_terminal_copy(self, ws_id: str) -> Optional[dict]:
        """Return deep copy of terminal if present and not expired; else None."""
        wid = _normalize_ws_id(ws_id)
        if wid == "":
            return None
        async with self._lock:
            self._evict_expired_locked()
            if wid not in self._data:
                return None
            if self._is_expired_locked(wid):
                self._data.pop(wid, None)
                self._created_monotonic.pop(wid, None)
                return None
            return copy.deepcopy(self._data[wid])

    async def pop_terminal(self, ws_id: str) -> Optional[dict]:
        """Remove and return terminal payload if present and not expired; else None."""
        wid = _normalize_ws_id(ws_id)
        if wid == "":
            return None
        async with self._lock:
            self._evict_expired_locked()
            if wid not in self._data:
                return None
            if self._is_expired_locked(wid):
                self._data.pop(wid, None)
                self._created_monotonic.pop(wid, None)
                return None
            payload = copy.deepcopy(self._data[wid])
            del self._data[wid]
            del self._created_monotonic[wid]
            return payload
