"""Runtime, admin-editable config backed by the `settings` table.

Unlike `app.config` (load-once from .env), these values can be changed from the admin
panel while the bot runs. A tiny in-memory cache keeps reads synchronous so keyboards
and middlewares don't need a DB session on every call.
"""
from __future__ import annotations

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.config import get_settings
from app.models import Setting

# Known keys (also the ones the admin panel exposes).
SUPPORT_URL = "support_url"
REQUIRED_CHANNEL = "required_channel"
REVIEWS_GROUP = "reviews_group"
SHOP_CHANNEL = "shop_channel"
CRYPTO_TOKEN = "crypto_token"
CRYPTO_ASSET = "crypto_asset"

CONFIG: dict[str, str] = {}


async def load(session: AsyncSession) -> None:
    """Load all settings from the DB into the in-memory cache."""
    result = await session.execute(select(Setting))
    CONFIG.clear()
    for row in result.scalars().all():
        CONFIG[row.key] = row.value


def get(key: str, default: str = "") -> str:
    """Synchronous cached read."""
    value = CONFIG.get(key, "")
    return value if value else default


def support_url() -> str:
    """Support link — runtime override, falling back to the .env value."""
    return get(SUPPORT_URL) or get_settings().support_url


def crypto_token() -> str:
    """CryptoBot Crypto Pay API token — runtime override, then .env."""
    return get(CRYPTO_TOKEN) or get_settings().crypto_pay_token


def crypto_asset() -> str:
    """Asset to charge (USDT/TON/…) — runtime override, then .env."""
    return get(CRYPTO_ASSET) or get_settings().crypto_pay_asset


def crypto_enabled() -> bool:
    """Automatic CryptoBot payments are available when a token is configured."""
    return bool(crypto_token().strip())


async def set_value(session: AsyncSession, key: str, value: str) -> None:
    """Upsert a setting and refresh the cache."""
    row = await session.get(Setting, key)
    if row is None:
        row = Setting(key=key, value=value)
        session.add(row)
    else:
        row.value = value
    await session.commit()
    CONFIG[key] = value
