"""
Claude Provider - Phase 24 ADR-052
====================================
Anthropic Claude API (claude-3-haiku, Tool Use 強制 JSON)

搬移自: openclaw.py _call_claude (L474-550)
特性: 最強推理、昂貴、CRITICAL/DELETE 強制使用

2026-04-02 ogt: Phase 24-A 從 openclaw.py 抽出
"""

from __future__ import annotations

import json
import time

import httpx
import structlog

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

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


class ClaudeProvider:
    """
    Anthropic Claude Cloud Provider

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

    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 "claude"

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

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

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

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

        start = time.perf_counter()
        try:
            client = await self._get_client()

            response = await client.post(
                "https://api.anthropic.com/v1/messages",
                headers={
                    "x-api-key": settings.CLAUDE_API_KEY,
                    "anthropic-version": "2023-06-01",
                    "content-type": "application/json",
                },
                json={
                    "model": get_model_registry().get_model("claude", "rca"),
                    "max_tokens": 2048,
                    "messages": [{"role": "user", "content": prompt}],
                    "tools": [{
                        "name": "submit_analysis",
                        "description": "Submit the RCA analysis result in structured format",
                        "input_schema": {
                            "type": "object",
                            "properties": {
                                "action_title": {"type": "string"},
                                "description": {"type": "string"},
                                "suggested_action": {"type": "string", "enum": ["RESTART_DEPLOYMENT", "DELETE_POD", "SCALE_DEPLOYMENT", "NO_ACTION"]},
                                "kubectl_command": {"type": "string"},
                                "target_resource": {"type": "string"},
                                "namespace": {"type": "string"},
                                "risk_level": {"type": "string", "enum": ["low", "medium", "critical"]},
                                "blast_radius": {
                                    "type": "object",
                                    "properties": {
                                        "affected_pods": {"type": "integer"},
                                        "estimated_downtime": {"type": "string"},
                                        "related_services": {"type": "array", "items": {"type": "string"}},
                                        "data_impact": {"type": "string", "enum": ["NONE", "READ_ONLY", "WRITE", "DESTRUCTIVE"]},
                                    },
                                    "required": ["affected_pods", "estimated_downtime", "related_services", "data_impact"],
                                },
                                "reasoning": {"type": "string"},
                                "deviation_analysis": {"type": "string"},
                                "confidence": {"type": "number"},
                                "affected_services": {"type": "array", "items": {"type": "string"}},
                            },
                            "required": ["action_title", "description", "suggested_action", "kubectl_command", "target_resource", "namespace", "risk_level", "blast_radius", "reasoning", "confidence"],
                        },
                    }],
                    "tool_choice": {"type": "tool", "name": "submit_analysis"},
                },
                timeout=30.0,
            )
            response.raise_for_status()
            data = response.json()

            # I2 修復: 追蹤 tokens/cost
            usage = data.get("usage", {})
            input_tokens = usage.get("input_tokens", 0)
            output_tokens = usage.get("output_tokens", 0)
            total_tokens = input_tokens + output_tokens
            # Claude Haiku: Input $0.25/1M, Output $1.25/1M
            cost_usd = (input_tokens * 0.00000025) + (output_tokens * 0.00000125)

            # 從 Tool Use 回應中提取 JSON
            for block in data.get("content", []):
                if block.get("type") == "tool_use" and block.get("name") == "submit_analysis":
                    tool_input = block.get("input", {})
                    latency = (time.perf_counter() - start) * 1000
                    logger.info("claude_provider_success", keys=list(tool_input.keys()), tokens=total_tokens, latency_ms=round(latency, 1))
                    return AIResult(
                        raw_response=json.dumps(tool_input),
                        success=True,
                        provider=self.name,
                        tokens=total_tokens,
                        cost_usd=cost_usd,
                        latency_ms=latency,
                    )

            # Fallback: text content
            for block in data.get("content", []):
                if block.get("type") == "text":
                    latency = (time.perf_counter() - start) * 1000
                    return AIResult(
                        raw_response=block.get("text", ""),
                        success=True,
                        provider=self.name,
                        tokens=total_tokens,
                        cost_usd=cost_usd,
                        latency_ms=latency,
                    )

            latency = (time.perf_counter() - start) * 1000
            return AIResult(raw_response="", success=False, provider=self.name, latency_ms=latency, error="No valid response")

        except Exception as e:
            latency = (time.perf_counter() - start) * 1000
            logger.warning("claude_provider_failed", error=str(e), latency_ms=round(latency, 1))
            return AIResult(raw_response="", success=False, provider=self.name, latency_ms=latency, error=str(e))

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

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