"""
Gemini Provider - Phase 24 ADR-052
====================================
Google Gemini Cloud API (gemini-2.0-flash)

搬移自: openclaw.py _call_gemini (L411-472)
特性: 穩定快速、JSON 輸出可靠、有費用 ($0.075/1M input)

2026-04-02 ogt: Phase 24-A 從 openclaw.py 抽出
2026-04-29 ogt + Claude Code: P0 SECRET LEAK 修復
  發現 prod log 出現完整 API key 明碼（feedback_secret_debug_output_ban 鐵律）
  根因：httpx HTTPStatusError str() 會包含完整 URL（含 ?key=... query string）
  修法：改用 x-goog-api-key header，並保留 _sanitize_error 當防線
"""

from __future__ import annotations

import re
import time

import httpx
import structlog

from src.core.config import get_settings
from src.services.ai_providers.interfaces import AIResult, is_provider_enabled_by_env
from src.services.model_registry import get_model_registry

logger = structlog.get_logger(__name__)
settings = get_settings()


# 2026-04-29 ogt + Claude Code: P0 SECRET LEAK
# httpx exception str() 會把完整 URL 含 ?key=AIzaSy... 寫進 error message
# 此 redact 函式在所有 logger 出口先過濾，防止 K8s pod log / Sentry / Telegram
# 任何下游接收端看到 key 明碼
_KEY_REDACT_PATTERN = re.compile(r"([?&])key=[^&\s'\"]+")


def _sanitize_error(error: object) -> str:
    """從錯誤訊息移除 ?key=xxx 等敏感 query string"""
    msg = str(error)
    return _KEY_REDACT_PATTERN.sub(r"\1key=<redacted>", msg)


class GeminiProvider:
    """
    Google Gemini Cloud Provider

    privacy_level: cloud (禁止機密資料)
    capabilities: rca, chat
    """

    def __init__(self) -> None:
        self._http_client: httpx.AsyncClient | None = None

    async def _get_client(self) -> httpx.AsyncClient:
        if self._http_client is None or self._http_client.is_closed:
            self._http_client = httpx.AsyncClient(timeout=httpx.Timeout(30.0, connect=10.0))
        return self._http_client

    @property
    def name(self) -> str:
        return "gemini"

    @property
    def is_enabled(self) -> bool:
        if not settings.GEMINI_API_KEY:
            return False
        return is_provider_enabled_by_env("gemini")

    @property
    def capabilities(self) -> set[str]:
        return {"rca", "chat"}

    @property
    def privacy_level(self) -> str:
        return "cloud"

    async def analyze(
        self,
        prompt: str,
        context: dict | None = None,
    ) -> AIResult:
        if not settings.GEMINI_API_KEY:
            return AIResult(raw_response="", success=False, provider=self.name, error="GEMINI_API_KEY not configured")

        start = time.perf_counter()
        try:
            client = await self._get_client()
            registry = get_model_registry()
            model_name = registry.get_model("gemini", "rca")

            response = await client.post(
                f"https://generativelanguage.googleapis.com/v1beta/models/{model_name}:generateContent",
                headers={"x-goog-api-key": settings.GEMINI_API_KEY},
                json={
                    "contents": [{"parts": [{"text": prompt}]}],
                    "generationConfig": {
                        "temperature": registry.get_provider_options("gemini").get("temperature", 0.1),
                        "maxOutputTokens": 2048,
                        "responseMimeType": "application/json",
                    },
                },
                timeout=30.0,
            )
            response.raise_for_status()
            data = response.json()
            text = data["candidates"][0]["content"]["parts"][0]["text"]

            # Token/Cost 追蹤
            usage = data.get("usageMetadata", {})
            prompt_tokens = usage.get("promptTokenCount", 0)
            completion_tokens = usage.get("candidatesTokenCount", 0)
            total_tokens = usage.get("totalTokenCount", prompt_tokens + completion_tokens)
            # Gemini 1.5 Flash: Input $0.075/1M, Output $0.30/1M
            cost_usd = (prompt_tokens * 0.000000075) + (completion_tokens * 0.0000003)
            latency = (time.perf_counter() - start) * 1000

            logger.info(
                "gemini_provider_success",
                response_length=len(text),
                total_tokens=total_tokens,
                cost_usd=f"${cost_usd:.6f}",
                latency_ms=round(latency, 1),
            )
            return AIResult(
                raw_response=text,
                success=True,
                provider=self.name,
                tokens=total_tokens,
                cost_usd=cost_usd,
                latency_ms=latency,
            )

        except Exception as e:
            latency = (time.perf_counter() - start) * 1000
            # 2026-04-29 ogt + Claude Code: P0 SECRET LEAK 修復
            # 之前 str(e) 會洩漏 URL 中的 ?key=AIzaSy... 到 prod log
            # 現用 _sanitize_error 過濾 ?key= query string
            safe_error = _sanitize_error(e)
            logger.warning("gemini_provider_failed", error=safe_error, latency_ms=round(latency, 1))
            return AIResult(raw_response="", success=False, provider=self.name, latency_ms=latency, error=safe_error)

    async def health_check(self) -> bool:
        return bool(settings.GEMINI_API_KEY)

    async def close(self) -> None:
        if self._http_client:
            await self._http_client.aclose()
            self._http_client = None
