from __future__ import annotations

import json
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any

from openclaw_lite.schema import ChatMessage
from openclaw_lite.utils import utc_now_iso


@dataclass(slots=True)
class SessionState:
    session_id: str
    provider_name: str
    model: str | None
    mode: str = "safe"
    messages: list[ChatMessage] = field(default_factory=list)
    updated_at: str = field(default_factory=utc_now_iso)
    metadata: dict[str, Any] = field(default_factory=dict)


class SessionStore:
    def __init__(self, base_dir: Path, default_provider: str, default_model: str | None, default_mode: str) -> None:
        self.base_dir = Path(base_dir)
        self.base_dir.mkdir(parents=True, exist_ok=True)
        self.default_provider = default_provider
        self.default_model = default_model
        self.default_mode = default_mode

    def _path(self, session_id: str) -> Path:
        safe = session_id.replace("/", "_")
        return self.base_dir / f"{safe}.json"

    def load(self, session_id: str) -> SessionState:
        path = self._path(session_id)
        if not path.exists():
            return SessionState(
                session_id=session_id,
                provider_name=self.default_provider,
                model=self.default_model,
                mode=self.default_mode,
            )
        raw = json.loads(path.read_text(encoding="utf-8"))
        return SessionState(
            session_id=raw["session_id"],
            provider_name=raw.get("provider_name", self.default_provider),
            model=raw.get("model", self.default_model),
            mode=raw.get("mode", self.default_mode),
            messages=[ChatMessage(**item) for item in raw.get("messages", [])],
            updated_at=raw.get("updated_at", utc_now_iso()),
            metadata=raw.get("metadata", {}),
        )

    def save(self, state: SessionState) -> None:
        state.updated_at = utc_now_iso()
        payload = {
            "session_id": state.session_id,
            "provider_name": state.provider_name,
            "model": state.model,
            "mode": state.mode,
            "updated_at": state.updated_at,
            "metadata": state.metadata,
            "messages": [
                {
                    "role": message.role,
                    "content": message.content,
                    "name": message.name,
                    "tool_call_id": message.tool_call_id,
                }
                for message in state.messages
            ],
        }
        self._path(state.session_id).write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8")

    def trim_history(self, state: SessionState, history_limit: int) -> None:
        if history_limit <= 0:
            return
        state.messages = state.messages[-history_limit:]
