import json
from pathlib import Path
from typing import Any

from sqlalchemy.ext.asyncio import AsyncSession

from app.services.settings_service import SettingsService

MESSAGES_DIR = Path(__file__).resolve().parents[1] / "messages"
MESSAGES_SETTING_KEY = "bot_messages"
MENU_SETTING_KEY = "bot_menu"

DEFAULT_MENU: list[dict[str, Any]] = [
    {"key": "buy", "label": "btn_buy", "action": "buy", "enabled": True, "sort": 1},
    {"key": "account", "label": "btn_account", "action": "account", "enabled": True, "sort": 2},
    {"key": "topup", "label": "btn_topup", "action": "topup", "enabled": True, "sort": 3},
    {"key": "referral", "label": "btn_referral", "action": "referral", "enabled": True, "sort": 4},
    {"key": "track", "label": "btn_track", "action": "track", "enabled": True, "sort": 5},
    {"key": "support", "label": "btn_support", "action": "support", "enabled": True, "sort": 6},
]


class MessageService:
    """Bot texts: JSON defaults overridden by admin-editable database values."""

    _defaults: dict[str, str] = {}

    def __init__(self, session: AsyncSession) -> None:
        self.session = session
        self.settings = SettingsService(session)

    @classmethod
    def defaults(cls, language: str = "fa") -> dict[str, str]:
        if not cls._defaults:
            path = MESSAGES_DIR / f"{language}.json"
            cls._defaults = json.loads(path.read_text(encoding="utf-8"))
        return dict(cls._defaults)

    async def all(self, language: str = "fa") -> dict[str, str]:
        messages = self.defaults(language)
        overrides = await self.settings.get(MESSAGES_SETTING_KEY, {}) or {}
        if isinstance(overrides, dict):
            messages.update({key: str(value) for key, value in overrides.items()})
        return messages

    async def get(self, key: str, language: str = "fa") -> str:
        return (await self.all(language)).get(key, key)

    async def overrides(self) -> dict[str, str]:
        values = await self.settings.get(MESSAGES_SETTING_KEY, {}) or {}
        return values if isinstance(values, dict) else {}

    async def update(self, values: dict[str, str]) -> dict[str, str]:
        current = await self.overrides()
        defaults = self.defaults()
        for key, value in values.items():
            if value is None or value == defaults.get(key):
                current.pop(key, None)
            else:
                current[key] = str(value)
        await self.settings.set(MESSAGES_SETTING_KEY, current, "Bot Messages")
        return current

    async def menu(self) -> list[dict[str, Any]]:
        stored = await self.settings.get(MENU_SETTING_KEY)
        items = stored if isinstance(stored, list) and stored else DEFAULT_MENU
        return sorted(
            [item for item in items if item.get("enabled", True)],
            key=lambda item: int(item.get("sort", 0)),
        )

    async def menu_all(self) -> list[dict[str, Any]]:
        stored = await self.settings.get(MENU_SETTING_KEY)
        items = stored if isinstance(stored, list) and stored else DEFAULT_MENU
        return sorted(items, key=lambda item: int(item.get("sort", 0)))

    async def update_menu(self, items: list[dict[str, Any]]) -> list[dict[str, Any]]:
        await self.settings.set(MENU_SETTING_KEY, items, "Bot Menu")
        return await self.menu_all()
