"""
SignOz MCP Tool Provider - ADR-015 模組化架構
=============================================

提供 SignOz 監控查詢工具：
- gold_metrics: 取得 Gold Metrics (RPS, Error Rate, P99)
- trace_url: 生成 Trace 查詢 URL
- system_metrics: 取得系統指標 (CPU/Disk)
- query_logs: 查詢日誌 (Phase 13.1 #77)
- error_logs_summary: 錯誤日誌摘要 (Phase 13.1 #77)

透過 DI 注入 SignOzClient，不直接 import services。

@see docs/adr/ADR-015-mcp-modular-architecture.md

版本: v1.1
最後修改: 2026-03-26 16:45 (台北時區)
修改者: Claude Code
變更: Phase 13.1 #77 新增 query_logs, error_logs_summary
"""

import uuid
from typing import Any

import structlog

from src.plugins.mcp.interfaces import MCPTool, MCPToolProvider, MCPToolResult

logger = structlog.get_logger(__name__)


class SignOzProvider(MCPToolProvider):
    """
    SignOz MCP Tool Provider

    封裝所有監控指標查詢操作。
    """

    def __init__(self) -> None:
        self._client = None

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

    def _get_client(self):
        """Lazy load SignOz client"""
        if self._client is None:
            from src.services.signoz_client import get_signoz_client
            self._client = get_signoz_client()
        return self._client

    async def list_tools(self) -> list[MCPTool]:
        return [
            MCPTool(
                name="gold_metrics",
                description="Get service Gold Metrics: RPS, Error Rate, P50/P95/P99 Latency",
                input_schema={
                    "type": "object",
                    "properties": {
                        "service_name": {"type": "string", "description": "Service name (e.g., awoooi-api)"},
                        "namespace": {"type": "string", "description": "Namespace (default: awoooi-prod)"},
                        "time_window_minutes": {"type": "integer", "description": "Time window in minutes (default: 10)"},
                    },
                    "required": ["service_name"],
                },
                server_name=self.name,
            ),
            MCPTool(
                name="trace_url",
                description="Generate SignOz trace URL for a service",
                input_schema={
                    "type": "object",
                    "properties": {
                        "service_name": {"type": "string", "description": "Service name"},
                        "window_minutes": {"type": "integer", "description": "Time window (default: 5)"},
                    },
                    "required": ["service_name"],
                },
                server_name=self.name,
            ),
            MCPTool(
                name="system_metrics",
                description="Get system metrics (CPU, Disk) for a host",
                input_schema={
                    "type": "object",
                    "properties": {
                        "host": {"type": "string", "description": "Host IP (default: 192.168.0.188)"},
                        "time_window_minutes": {"type": "integer", "description": "Time window (default: 5)"},
                    },
                },
                server_name=self.name,
            ),
            MCPTool(
                name="query_logs",
                description="Query logs from SignOz (Phase 13.1 #77). Use for CI failure diagnosis or service debugging.",
                input_schema={
                    "type": "object",
                    "properties": {
                        "service_name": {"type": "string", "description": "Service name (e.g., awoooi-api, awoooi-worker)"},
                        "severity": {"type": "string", "description": "Log severity filter (ERROR, WARN, INFO, DEBUG). Comma-separated for multiple."},
                        "search_text": {"type": "string", "description": "Text to search in log messages"},
                        "time_window_minutes": {"type": "integer", "description": "Time window in minutes (default: 30)"},
                        "limit": {"type": "integer", "description": "Max logs to return (default: 100)"},
                    },
                },
                server_name=self.name,
            ),
            MCPTool(
                name="error_logs_summary",
                description="Get error logs summary with counts and sample messages. Useful for quick diagnosis.",
                input_schema={
                    "type": "object",
                    "properties": {
                        "service_name": {"type": "string", "description": "Service name (required)"},
                        "time_window_minutes": {"type": "integer", "description": "Time window (default: 60)"},
                    },
                    "required": ["service_name"],
                },
                server_name=self.name,
            ),
        ]

    async def execute(
        self,
        tool_name: str,
        parameters: dict[str, Any],
    ) -> MCPToolResult:
        execution_id = str(uuid.uuid4())[:8]
        client = self._get_client()

        try:
            if tool_name == "gold_metrics":
                output = await self._gold_metrics(client, parameters)
            elif tool_name == "trace_url":
                output = self._trace_url(client, parameters)
            elif tool_name == "system_metrics":
                output = await self._system_metrics(client, parameters)
            elif tool_name == "query_logs":
                output = await self._query_logs(client, parameters)
            elif tool_name == "error_logs_summary":
                output = await self._error_logs_summary(client, parameters)
            else:
                return MCPToolResult(
                    success=False,
                    execution_id=execution_id,
                    error=f"Unknown tool: {tool_name}",
                )

            return MCPToolResult(
                success=True,
                execution_id=execution_id,
                output=output,
            )

        except Exception as e:
            logger.exception("signoz_provider_error", tool=tool_name, error=str(e))
            return MCPToolResult(
                success=False,
                execution_id=execution_id,
                error=str(e),
            )

    async def _gold_metrics(self, client, parameters: dict) -> dict:
        service_name = parameters.get("service_name", "")
        if not service_name:
            return {"error": "Missing 'service_name' parameter"}

        namespace = parameters.get("namespace", "awoooi-prod")
        time_window = parameters.get("time_window_minutes", 10)

        metrics = await client.get_gold_metrics(
            service_name=service_name,
            namespace=namespace,
            time_window_minutes=time_window,
        )

        return {
            "service_name": metrics.service_name,
            "namespace": metrics.namespace,
            "rps": round(metrics.rps, 2),
            "rps_trend": metrics.rps_trend,
            "error_rate": round(metrics.error_rate, 2),
            "error_count": metrics.error_count,
            "total_requests": metrics.total_requests,
            "p50_latency_ms": round(metrics.p50_latency_ms, 1),
            "p95_latency_ms": round(metrics.p95_latency_ms, 1),
            "p99_latency_ms": round(metrics.p99_latency_ms, 1),
            "latency_trend": metrics.latency_trend,
            "summary": metrics.to_summary(),
        }

    def _trace_url(self, client, parameters: dict) -> dict:
        service_name = parameters.get("service_name", "")
        if not service_name:
            return {"error": "Missing 'service_name' parameter"}

        window_minutes = parameters.get("window_minutes", 5)
        url = client.generate_trace_url(
            service_name=service_name,
            window_minutes=window_minutes,
        )

        return {
            "service_name": service_name,
            "trace_url": url,
            "window_minutes": window_minutes,
        }

    async def _system_metrics(self, client, parameters: dict) -> dict:
        host = parameters.get("host", "192.168.0.188")
        time_window = parameters.get("time_window_minutes", 5)

        metrics = await client.get_system_metrics(
            _host=host,
            time_window_minutes=time_window,
        )

        return {
            "host": host,
            "cpu": metrics.get("cpu", {}),
            "disk": metrics.get("disk", {}),
            "time_range": metrics.get("time_range", {}),
        }

    async def _query_logs(self, client, parameters: dict) -> dict:
        """Query logs from SignOz (Phase 13.1 #77)"""
        service_name = parameters.get("service_name")
        severity = parameters.get("severity")
        search_text = parameters.get("search_text")
        time_window = parameters.get("time_window_minutes", 30)
        limit = parameters.get("limit", 100)

        logs = await client.get_logs(
            service_name=service_name,
            severity=severity,
            search_text=search_text,
            time_window_minutes=time_window,
            limit=limit,
        )

        return {
            "logs": logs,
            "count": len(logs),
            "filters": {
                "service_name": service_name,
                "severity": severity,
                "search_text": search_text,
                "time_window_minutes": time_window,
            },
        }

    async def _error_logs_summary(self, client, parameters: dict) -> dict:
        """Get error logs summary (Phase 13.1 #77)"""
        service_name = parameters.get("service_name")
        if not service_name:
            return {"error": "Missing 'service_name' parameter"}

        time_window = parameters.get("time_window_minutes", 60)

        summary = await client.get_error_logs_summary(
            service_name=service_name,
            time_window_minutes=time_window,
        )

        return summary

    async def health_check(self) -> bool:
        """Check if SignOz is accessible"""
        try:
            # SignOz client initialization is the health check
            self._get_client()
            return True
        except Exception:
            return False
