# backend/app/services/settings_service.py
# app_setting(영속) ↔ runtime_config(인메모리 오버레이) 동기화.
from sqlmodel import Session, select

from .. import runtime_config
from ..models import AppSetting, now


def _upsert(session: Session, key: str, value: str | None) -> None:
    """value=None/빈 → 행 삭제(기본으로 복귀). 그 외 → upsert."""
    row = session.get(AppSetting, key)
    if value is None or (isinstance(value, str) and value.strip() == ""):
        if row:
            session.delete(row)
        return
    if row:
        row.value = str(value)
        row.updated_at = now()
        session.add(row)
    else:
        session.add(AppSetting(key=key, value=str(value)))


def update_llm(
    session: Session,
    *,
    provider: str | None = None,
    model: str | None = None,
    host: str | None = None,
    timeout: float | None = None,
) -> None:
    """LLM 설정을 영속(app_setting)하고 런타임 오버레이에 즉시 반영.

    provider 가 'auto'(=env 기본과 동등하게 둘 수도 있으나) 라도 명시 저장은 허용한다.
    None 인 필드는 건드리지 않는다(부분 갱신)."""
    fields: dict[str, object | None] = {}
    if provider is not None:
        if provider.strip() == "":
            fields["llm.provider"] = None  # 빈 값 → 기본(env)으로 되돌리기
        elif provider not in runtime_config._PROVIDERS:
            raise ValueError(f"provider must be one of {runtime_config._PROVIDERS}")
        else:
            fields["llm.provider"] = provider
    if model is not None:
        fields["llm.model"] = model
    if host is not None:
        fields["llm.host"] = host
    if timeout is not None:
        # timeout<=0 은 '기본으로 되돌리기' 신호(프론트 리셋용).
        fields["llm.timeout"] = None if timeout <= 0 else timeout

    for key, val in fields.items():
        _upsert(session, key, None if val is None else str(val))
    session.commit()

    # 영속 후 DB → 오버레이 재적재(부분 삭제까지 일관되게 반영)
    runtime_config.load_from_db(session)


def overlay_active(session: Session) -> bool:
    """LLM 오버레이 행이 하나라도 있으면 True."""
    rows = session.exec(select(AppSetting)).all()
    return any(r.key in runtime_config.LLM_KEYS for r in rows)
