from __future__ import annotations

from datetime import UTC, datetime
from typing import Any

from sdk.interface import User, UserSettings

# Keep the prototype backend self-contained; do not import these from sdk.mock.
DEFAULT_SKILLS: dict[str, bool] = {
    "web-search": True,
    "fetch-url": True,
    "email": False,
    "browser": False,
    "image-gen": False,
    "files": True,
}
DEFAULT_SAFETY: dict[str, bool] = {
    "email-send": True,
    "file-delete": True,
    "social-post": True,
}
DEFAULT_SOUL: dict[str, str] = {"name": "Лямбда", "instructions": ""}
DEFAULT_PLAN: dict[str, Any] = {
    "name": "Beta",
    "tokens_used": 0,
    "tokens_limit": 1000,
}


class PrototypeStateStore:
    def __init__(self) -> None:
        self._users: dict[str, User] = {}
        self._settings: dict[str, dict[str, Any]] = {}
        self._saved_sessions: dict[str, list[dict[str, str]]] = {}
        self._context_last_tokens_used: dict[str, int] = {}
        self._context_current_session: dict[str, str] = {}

    async def get_or_create_user(
        self,
        external_id: str,
        platform: str,
        display_name: str | None = None,
    ) -> User:
        key = f"{platform}:{external_id}"
        existing = self._users.get(key)
        if existing is not None:
            stored = existing.model_copy(update={"is_new": False})
            self._users[key] = stored
            return stored.model_copy()

        user = User(
            user_id=f"usr-{platform}-{external_id}",
            external_id=external_id,
            platform=platform,
            display_name=display_name,
            created_at=datetime.now(UTC),
            is_new=True,
        )
        self._users[key] = user.model_copy(update={"is_new": False})
        return user.model_copy()

    async def get_settings(self, user_id: str) -> UserSettings:
        stored = self._settings.get(user_id, {})
        return UserSettings(
            skills={**DEFAULT_SKILLS, **stored.get("skills", {})},
            connectors=dict(stored.get("connectors", {})),
            soul={**DEFAULT_SOUL, **stored.get("soul", {})},
            safety={**DEFAULT_SAFETY, **stored.get("safety", {})},
            plan={**DEFAULT_PLAN, **stored.get("plan", {})},
        )

    async def update_settings(self, user_id: str, action: Any) -> None:
        settings = self._settings.setdefault(user_id, {})

        if action.action == "toggle_skill":
            skills = settings.setdefault("skills", DEFAULT_SKILLS.copy())
            skills[action.payload["skill"]] = action.payload.get("enabled", True)
        elif action.action == "set_soul":
            soul = settings.setdefault("soul", DEFAULT_SOUL.copy())
            soul[action.payload["field"]] = action.payload["value"]
        elif action.action == "set_safety":
            safety = settings.setdefault("safety", DEFAULT_SAFETY.copy())
            safety[action.payload["trigger"]] = action.payload.get("enabled", True)

    async def add_saved_session(
        self,
        user_id: str,
        name: str,
        *,
        source_context_id: str | None = None,
    ) -> None:
        sessions = self._saved_sessions.setdefault(user_id, [])
        session = {"name": name, "created_at": datetime.now(UTC).isoformat()}
        if source_context_id is not None:
            session["source_context_id"] = source_context_id
        sessions.append(session)

    async def list_saved_sessions(self, user_id: str) -> list[dict[str, str]]:
        return [dict(session) for session in self._saved_sessions.get(user_id, [])]

    async def get_last_tokens_used_for_context(self, context_id: str) -> int:
        return self._context_last_tokens_used.get(context_id, 0)

    async def set_last_tokens_used_for_context(self, context_id: str, tokens: int) -> None:
        self._context_last_tokens_used[context_id] = tokens

    async def get_current_session_for_context(self, context_id: str) -> str | None:
        return self._context_current_session.get(context_id)

    async def set_current_session_for_context(self, context_id: str, name: str) -> None:
        self._context_current_session[context_id] = name

    async def clear_current_session_for_context(self, context_id: str) -> None:
        self._context_current_session.pop(context_id, None)

    async def get_last_tokens_used(self, context_id: str) -> int:
        return await self.get_last_tokens_used_for_context(context_id)

    async def set_last_tokens_used(self, context_id: str, tokens: int) -> None:
        await self.set_last_tokens_used_for_context(context_id, tokens)

    async def get_current_session(self, context_id: str) -> str | None:
        return await self.get_current_session_for_context(context_id)

    async def set_current_session(self, context_id: str, name: str) -> None:
        await self.set_current_session_for_context(context_id, name)

    async def clear_current_session(self, context_id: str) -> None:
        await self.clear_current_session_for_context(context_id)
