"""Lightweight in-process cache for per-section cabinet button styles.

Avoids circular imports between ``cabinet.routes`` and ``app.utils.miniapp_buttons``
by keeping the cache and its helpers in a dedicated module.
"""

import json

import structlog

from app.database.database import AsyncSessionLocal


logger = structlog.get_logger(__name__)

# ---- Defaults per section ------------------------------------------------

DEFAULT_BUTTON_STYLES: dict[str, dict] = {
    'home': {'style': 'primary', 'icon_custom_emoji_id': '', 'enabled': True, 'labels': {}},
    'subscription': {'style': 'success', 'icon_custom_emoji_id': '', 'enabled': True, 'labels': {}},
    'balance': {'style': 'primary', 'icon_custom_emoji_id': '', 'enabled': True, 'labels': {}},
    'referral': {'style': 'success', 'icon_custom_emoji_id': '', 'enabled': True, 'labels': {}},
    'support': {'style': 'primary', 'icon_custom_emoji_id': '', 'enabled': True, 'labels': {}},
    'info': {'style': 'primary', 'icon_custom_emoji_id': '', 'enabled': True, 'labels': {}},
    'admin': {'style': 'danger', 'icon_custom_emoji_id': '', 'enabled': True, 'labels': {}},
}

BOT_LOCALES = ('ru', 'en', 'ua', 'zh', 'fa')

SECTIONS = list(DEFAULT_BUTTON_STYLES.keys())

# Map callback_data values to their logical section name.
CALLBACK_TO_SECTION: dict[str, str] = {
    'menu_profile_unavailable': 'home',
    'back_to_menu': 'home',
    'menu_subscription': 'subscription',
    'subscription': 'subscription',
    'subscription_extend': 'subscription',
    'subscription_upgrade': 'subscription',
    'subscription_connect': 'subscription',
    'subscription_resume_checkout': 'subscription',
    'return_to_saved_cart': 'subscription',
    'menu_buy': 'subscription',
    'buy_traffic': 'subscription',
    'menu_balance': 'balance',
    'balance_topup': 'balance',
    'menu_referrals': 'referral',
    'menu_referral': 'referral',
    'menu_support': 'support',
    'menu_info': 'info',
    'admin_panel': 'admin',
}

# DB key used for storage.
BUTTON_STYLES_KEY = 'CABINET_BUTTON_STYLES'

# Valid Telegram Bot API style values.
VALID_STYLES = frozenset({'primary', 'success', 'danger'})

# All style values accepted by the admin API ('default' = no color, Telegram default).
ALLOWED_STYLE_VALUES = VALID_STYLES | {'default'}

# ---- Module-level cache ---------------------------------------------------

_cached_styles: dict[str, dict] | None = None


def _deep_copy_styles(source: dict[str, dict]) -> dict[str, dict]:
    """Return a deep copy of styles dict (copies nested ``labels`` dicts)."""
    return {section: {**cfg, 'labels': dict(cfg.get('labels', {}))} for section, cfg in source.items()}


def get_cached_button_styles() -> dict[str, dict]:
    """Return the current merged config (DB overrides + defaults).

    If the cache has not been loaded yet, returns defaults.
    """
    if _cached_styles is not None:
        return _deep_copy_styles(_cached_styles)
    return _deep_copy_styles(DEFAULT_BUTTON_STYLES)


async def load_button_styles_cache() -> dict[str, dict]:
    """Load button styles from DB and refresh the module cache.

    Called at bot startup and after admin updates via the cabinet API.
    """
    global _cached_styles

    merged = _deep_copy_styles(DEFAULT_BUTTON_STYLES)

    try:
        from sqlalchemy import select

        from app.database.models import SystemSetting

        async with AsyncSessionLocal() as session:
            result = await session.execute(select(SystemSetting).where(SystemSetting.key == BUTTON_STYLES_KEY))
            setting = result.scalar_one_or_none()
            if setting and setting.value:
                db_data: dict = json.loads(setting.value)
                for section, overrides in db_data.items():
                    if section in merged and isinstance(overrides, dict):
                        if overrides.get('style') in ALLOWED_STYLE_VALUES:
                            merged[section]['style'] = overrides['style']
                        if isinstance(overrides.get('icon_custom_emoji_id'), str):
                            merged[section]['icon_custom_emoji_id'] = overrides['icon_custom_emoji_id']
                        if isinstance(overrides.get('enabled'), bool):
                            merged[section]['enabled'] = overrides['enabled']
                        if isinstance(overrides.get('labels'), dict):
                            merged[section]['labels'] = {
                                k: v
                                for k, v in overrides['labels'].items()
                                if isinstance(k, str) and isinstance(v, str) and k in BOT_LOCALES
                            }
    except Exception:
        logger.exception('Failed to load button styles from DB, using defaults')

    _cached_styles = merged
    logger.info('Button styles cache loaded', list=list(merged.keys()))
    return merged
