"""Принудительное применение матрицы «пресет → настройки» на живой инсталляции.

Бутстрап (`main.py::lifespan`,
`InstanceSettingsService.ensure_bootstrapped`) применяет overrides пресета
инсталлятора (`BOOTSTRAP_CHAT_ENABLED`/`BOOTSTRAP_TRANSCRIPTION_ENABLED`/
`BOOTSTRAP_AI_LEVEL` в `.env`, см. `core.config.Settings`) только на чистой
БД (`INSERT ... ON CONFLICT DO NOTHING`) — строки уже существующей
инсталляции он не трогает. Этот скрипт запускает install.sh при ПОВТОРНОМ
запуске с другим пресетом на живой инсталляции, после подтверждения в
опроснике («обновить настройки модулей под пресет?») либо флага `--yes`
самого install.sh.

Управляет РОВНО 4 ключами (`chat`, `transcriber`, `summarizer`, `ai_level`,
см. `services.instance_settings.BOOTSTRAP_MANAGED_KEYS`) — остальные
настройки инстанса (таймзона, рассылка саммари, регистрация) этот скрипт не
трогает. Без `--force` пишет только ОТСУТСТВУЮЩИЕ из них — страховка от
молчаливой потери ручных правок администратора; с `--force` перезаписывает
все 4 значениями текущего пресета (`transcriber`/`summarizer` — целиком, тем
же дефолтом `plugins.yaml` + `enabled`, что и обычный бутстрап: подмена
provider/model для уровней `medium`/`max` происходит при чтении конфигурации,
см. `services.instance_settings.load_effective_config`, а не при записи).

`ai_level` пишется напрямую в БД, минуя валидацию доступности
(`services.ai_levels.detect_ai_levels`): модели уровня `medium`/`max`
докачиваются отдельными профилями `docker-compose` уже ПОСЛЕ первого запуска
install.sh, и жёсткая валидация здесь давала бы ложный отказ применения
пресета, пока докачка не завершена — вместо этого пишем предупреждение в лог.

Запустить: `uv run python -m scripts.apply_preset_settings [--force]`
"""

import argparse
import asyncio
import logging

from sqlalchemy import select
from sqlalchemy.dialects.postgresql import insert as pg_insert

from core.config import get_settings
from core.db import async_session_maker, engine
from core.plugins.config import load_plugins_config
from models.instance_setting import InstanceSetting
from services.instance_settings import (
    BOOTSTRAP_MANAGED_KEYS,
    bootstrap_overrides_from_settings,
    build_bootstrap_defaults,
)

logger = logging.getLogger(__name__)


async def apply_preset_settings(*, force: bool) -> list[str]:
    """Применить текущий пресет (`BOOTSTRAP_*`) к управляемым ключам `instance_settings`.

    Возвращает список фактически записанных ключей (пустой — писать было
    нечего: все 4 ключа уже существуют и `force=False`).
    """
    settings = get_settings()
    plugins = load_plugins_config(settings.plugins_config_path)
    overrides = bootstrap_overrides_from_settings(settings)
    defaults = build_bootstrap_defaults(plugins, overrides)

    async with async_session_maker() as session:
        result = await session.execute(
            select(InstanceSetting.key).where(InstanceSetting.key.in_(BOOTSTRAP_MANAGED_KEYS))
        )
        existing_keys = set(result.scalars().all())

        written: list[str] = []
        for key in BOOTSTRAP_MANAGED_KEYS:
            if key in existing_keys and not force:
                continue
            value = defaults[key]
            stmt = (
                pg_insert(InstanceSetting)
                .values(key=key, value=value)
                .on_conflict_do_update(index_elements=["key"], set_={"value": value})
            )
            await session.execute(stmt)
            written.append(key)
        await session.commit()

    if "ai_level" in written:
        logger.warning(
            "apply_preset_settings: ai_level=%r записан напрямую, без проверки доступности "
            "(detect_ai_levels) — модели уровня могут ещё докачиваться профилем docker-compose",
            defaults["ai_level"]["level"],
        )
    logger.info(
        "apply_preset_settings: обновлены ключи %s (force=%s, пропущены как уже существующие: %s)",
        written or "нет",
        force,
        sorted(existing_keys - set(written)) or "нет",
    )
    return written


def _parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description="Применить матрицу «пресет → настройки» инсталлятора к instance_settings."
    )
    parser.add_argument(
        "--force",
        action="store_true",
        help="перезаписать уже существующие ключи (без флага пишутся только отсутствующие)",
    )
    return parser.parse_args()


async def _main() -> None:
    logging.basicConfig(
        level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s"
    )
    args = _parse_args()
    await apply_preset_settings(force=args.force)
    await engine.dispose()


if __name__ == "__main__":
    asyncio.run(_main())
