"""Session state persistence across Codex hook invocations.

Codex has no SessionEnd event, so stale state files are cleaned up
via a GC pass on SessionStart (files older than 24 hours).
"""
from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

from staso._common.state import (
    BaseHookState,
    acquire_lock_in,
    delete_state_from,
    gc_stale_in,
    load_state_from,
    release_lock_in,
    save_state_to,
    validate_session_id,
)


@dataclass
class HookState(BaseHookState):
    """Per-session state for Codex hook invocations."""

    turns_processed: int = 0
    transcript_path: str = ""


def _state_dir() -> Path:
    return Path.home() / ".staso" / "codex"


def load_state(session_id: str) -> HookState | None:
    return load_state_from(_state_dir(), HookState, session_id)  # type: ignore[return-value]


def save_state(state: HookState) -> None:
    save_state_to(_state_dir(), state)


def delete_state(session_id: str) -> None:
    delete_state_from(_state_dir(), session_id)


def acquire_lock(session_id: str, max_retries: int = 30, retry_delay: float = 0.1) -> bool:
    return acquire_lock_in(_state_dir(), session_id, max_retries, retry_delay)


def release_lock(session_id: str) -> None:
    release_lock_in(_state_dir(), session_id)


def gc_stale_states(max_age_seconds: int = 86400) -> None:
    """Remove state files and stale lock dirs older than max_age_seconds."""
    gc_stale_in(_state_dir(), max_age_seconds)
