"""Multi-turn dialogue manager — session context persistence for LLM conversations.
Enables cross-turn context for complex analysis (strategy review, morning briefing)."""

from __future__ import annotations
import json, time
from pathlib import Path
from typing import Any, Optional

MAX_TURNS = 10
SESSION_TTL_SEC = 3600

class DialogueSession:
    def __init__(self, session_id: str, role: str = "analyst"):
        self.session_id = session_id
        self.role = role
        self.turns: list[dict] = []
        self.created_at = time.time()
        self.last_active = time.time()

    def add_turn(self, role: str, content: str) -> None:
        self.turns.append({"role": role, "content": content, "ts": time.time()})
        if len(self.turns) > MAX_TURNS * 2:
            self.turns = self.turns[-(MAX_TURNS * 2):]
        self.last_active = time.time()

    def get_context(self, max_turns: int = 6) -> str:
        recent = self.turns[-(max_turns * 2):]
        return "\n".join(f"[{t['role']}]: {t['content'][:500]}" for t in recent)

    def is_expired(self) -> bool:
        return time.time() - self.last_active > SESSION_TTL_SEC

class DialogueManager:
    def __init__(self, store_dir: Optional[Path] = None):
        self._sessions: dict[str, DialogueSession] = {}
        self._dir = store_dir or Path("data/dialogues")
        self._dir.mkdir(parents=True, exist_ok=True)

    def get_or_create(self, session_id: str, role: str = "analyst") -> DialogueSession:
        if session_id in self._sessions:
            sess = self._sessions[session_id]
            if not sess.is_expired(): return sess
        sess = DialogueSession(session_id, role)
        self._sessions[session_id] = sess
        return sess

    def end_session(self, session_id: str) -> None:
        self._sessions.pop(session_id, None)

    def cleanup_expired(self) -> int:
        expired = [sid for sid, s in self._sessions.items() if s.is_expired()]
        for sid in expired: self._sessions.pop(sid, None)
        return len(expired)

_dialogue_mgr: Optional[DialogueManager] = None
def get_dialogue_manager() -> DialogueManager:
    global _dialogue_mgr
    if _dialogue_mgr is None: _dialogue_mgr = DialogueManager()
    return _dialogue_mgr
