"""Kimi Code 订阅 plan — 静态 Console API Key 适配器。

Kimi Code Console（`kimi.com/code/console`）签发的 API Key 走**订阅额度**，命中与 OAuth
`kimi-code` **相同**的 coding 端点（`https://api.kimi.com/coding/v1`，OpenAI 兼容）+ 相同
model `kimi-for-coding`。

**实测纠正（2026-06-20）**：coding 端点会校验 `User-Agent`，对非 allow-list 客户端返回
`403 access_terminated_error: only available for Coding Agents such as Kimi CLI, Claude Code,
Roo Code, ...`——**无论用静态 key 还是 OAuth token**。即静态 key 仅解决鉴权（无 401），但
UA 门禁（403）依旧。故本适配器**也必须发**与 OAuth 相同的伪造客户端头集
（`kimi_code_headers()`：`KimiCLI/1.37.0` + `X-Msh-*`），否则 403。早先「纯 key 无需伪造头、
ToS 合规」的判断被实测推翻——**两条订阅路径都需 UA 伪造 = 同样的 ToS 违规/封号风险**。本路径
相对 OAuth 的唯一优势是用静态 Console key（无 token 刷新机制），风险等同。真正合规的只有
按量付费的 Moonshot 平台 key（provider `kimi`）。

唯一与普通 OpenAI 兼容 provider 的另一区别：coding 端点跑 `kimi-for-coding` 且 **thinking 开启**，
Moonshot 后端对「thinking + 强制 `tool_choice`」返回 `400`。因此结构化输出走 instructor
**JSON 模式**（复用 `build_kimi_code_structured_client`），而非默认 TOOLS 模式。
"""

from __future__ import annotations

from openai import AsyncOpenAI

from .kimi_code import (
    KIMI_CODE_BASE_URL,
    build_kimi_code_structured_client,
    kimi_code_headers,
)
from .openai_compat import OpenAICompatAdapter, StructuredClient

#: provider 名（与 OAuth 的 `kimi-code`、moonshot 的 `kimi` 均分离，便于档位切换）。
KIMI_CODE_KEY_PROVIDER = "kimi-code-key"


def build_kimi_code_key_client(api_key: str, *, base_url: str | None = None) -> AsyncOpenAI:
    """构造 coding 端点客户端（key → bearer + **伪造客户端头**，coding base）。

    实测：coding 端点据 `User-Agent` 做 allow-list 门禁，缺伪造头 → 403。故与 OAuth 的
    `build_kimi_code_client` 一样必须带 `default_headers=kimi_code_headers()`
    （`KimiCLI/1.37.0` + `X-Msh-*`）；唯一区别是凭据来源是静态 Console key 而非 OAuth token。
    """
    return AsyncOpenAI(
        api_key=api_key,
        base_url=base_url or KIMI_CODE_BASE_URL,
        default_headers=kimi_code_headers(),
    )


class KimiCodeKeyAdapter(OpenAICompatAdapter):
    """Kimi Code 静态 Key 适配器：OpenAI 兼容 + 伪造客户端头 + JSON 模式结构化。

    model（`kimi-for-coding`）经 `.complete(req, model)` 由路由/档位传入，**不**在此硬编码。
    结构化输出强制走 JSON 模式（thinking 兼容）；发与 OAuth 相同的伪造头以过 coding 端点 UA 门禁。
    """

    def __init__(
        self, client: AsyncOpenAI, *, structured_client: StructuredClient | None = None
    ) -> None:
        super().__init__(
            KIMI_CODE_KEY_PROVIDER,
            client,
            structured_client=structured_client or build_kimi_code_structured_client(client),
        )
