"""VLM 호출에 **키를 실어 보내는** 한 자리 (#92, 2026-08-27).

## 왜 이 파일이 있나 — 모델 이름만 바꾸면 호출이 선다

`llm_completion` 도 `litellm.completion` 도 **OpenAI 가 아닌 모델에는
키를 안 끼운다**. 그런데 VLM 자리들은 전부 이렇게 생겼다:

    # from app.core.openai_keys import has_openai_key
    # if not has_openai_key(): raise ...          ← OpenAI 만 본다
    # resp = litellm.completion(model=model, ...)  ← api_key 가 없다

기본 모델이 OpenAI 였을 때는 litellm 이 환경변수에서 키를 찾아 그럭저럭
돌았다. Sol → gemini 로 바꾸는 순간 **둘 다 깨진다** — 관문은 엉뚱한
키를 보고, 호출은 키 없이 나간다.

zoom(`zoom_continuity_render_service.vlm_locate_bbox`)에서 한 번 고쳤는데
같은 결함이 다섯 자리에 그대로 남아 있었다(2026-08-27 Codex BLOCK).
다섯 번 베끼면 여섯 번째에 또 빠뜨린다 — 그래서 한 자리로 둔다.
"""
from __future__ import annotations

from typing import Any, Dict, Type

__all__ = ["provider_of", "auth_kwargs"]


def provider_of(model: str) -> str:
    """litellm 이 이 모델을 어느 provider 로 푸는지 — **접두가 곧 답**이다.

    접두가 없으면 OpenAI 다 (`gpt-5.6-sol` 등). 접두 규칙은 Router
    등록부와 같다(`llm_client.py:538`) — 여기서 지어낸 것이 아니다.
    """
    m = (model or "").strip()
    return m.split("/", 1)[0] if "/" in m else "openai"


def auth_kwargs(
    model: str, error_cls: Type[Exception] = RuntimeError
) -> Dict[str, Any]:
    """관문과 키를 **한 번에** — 이 모델을 부를 때 함께 넘길 kwargs.

    gemini 는 키 풀에서 하나 꺼내 `api_key=` 로 명시 전달한다. OpenAI 는
    브로커(`llm_completion`)가 활성 슬롯의 키를 알아서 끼우므로 비운다.
    키가 없으면 **부르지 않고** `error_cls` 를 올린다 — provider 별로 본다
    (`has_openai_key()` 하나로 막으면 gemini 를 부르면서 OpenAI 키를
    확인하게 된다).

    ★**유료 호출 하나에 한 번만 부른다.** 키 풀은 라운드로빈이라 두 번
     부르면 카운터가 두 칸 돈다 — 관문이 A 를 태워 버리고 실제 요청은
     늘 B 로 나간다. 키가 둘일 때 B 가 막히면 멀쩡한 A 가 있어도 전부
     실패한다. 그래서 관문과 kwargs 를 **한 함수로 합쳤다** — 나눠 두면
     호출부가 두 번 부르는 것을 막을 방법이 없다
     (2026-08-27 Codex BLOCK).
    """
    if provider_of(model) == "gemini":
        from app.modules.llm.gemini_key_pool import get_next_key

        try:
            key = get_next_key()
        except Exception as exc:  # noqa: BLE001 — 키 풀이 비면 RuntimeError
            raise error_cls(
                f"GEMINI_API_KEY missing or empty; refusing to call {model!r}"
            ) from exc
        if not key:
            raise error_cls(
                f"GEMINI_API_KEY missing or empty; refusing to call {model!r}"
            )
        return {"api_key": key}

    from app.core.openai_keys import has_openai_key

    if not has_openai_key():
        raise error_cls(
            f"OPENAI_API_KEY missing or empty; refusing to call {model!r}"
        )
    return {}
