# xulcan/ledger/adapters/in_memory.py
from typing import Dict, List, Optional
from xulcan.core.primitives import MachineID
from xulcan.history.events import RunEvent, EventType
from xulcan.ledger.base import BaseLedgerAdapter


class InMemoryLedger(BaseLedgerAdapter):
    """Reference implementation using ephemeral RAM storage."""

    def __init__(self):
        self._store: Dict[MachineID, List[RunEvent]] = {}
        self._sessions: Dict[str, MachineID] = {}  # session_key → último run_id

    async def _append_impl(self, event: RunEvent) -> None:
        """Writes the event to the in-memory list."""
        run_id = event.run_id
        if run_id not in self._store:
            if event.type != EventType.RUN_CREATED:
                raise ValueError(f"First event for run {run_id} must be RUN_CREATED")
            self._store[run_id] = []
        self._store[run_id].append(event)

    async def _get_events_impl(self, run_id: MachineID, from_index: int = 0) -> List[RunEvent]:
        """Returns slice of events list."""
        if run_id not in self._store:
            return []
        return self._store[run_id][from_index:]

    async def _tag_run_impl(self, run_id: MachineID, session_key: str) -> None:
        """Asocia la session_key con el run_id más reciente."""
        self._sessions[session_key] = run_id

    async def _get_last_run_id_impl(self, session_key: str) -> Optional[MachineID]:
        """Devuelve el último run_id de la sesión, o None si es nueva."""
        return self._sessions.get(session_key)