"""
IIncidentProcessor - 事件處理器介面
===================================

定義 Incident 處理的標準介面

統帥鐵律:
- 禁止告警風暴 (相關告警必須聚合)
- 禁止 O(N) 掃描 (所有查詢必須 O(1))
- 禁止 Race Condition (所有寫入必須原子操作)
"""

from abc import ABC, abstractmethod
from datetime import datetime
from enum import Enum
from typing import Any
from pydantic import BaseModel, Field
from uuid import UUID


class IncidentStatus(str, Enum):
    """事件狀態"""
    INVESTIGATING = "investigating"
    MITIGATING = "mitigating"
    RESOLVED = "resolved"
    CLOSED = "closed"


class Severity(str, Enum):
    """嚴重等級"""
    P0 = "P0"  # Critical
    P1 = "P1"  # High
    P2 = "P2"  # Warning
    P3 = "P3"  # Info


class Signal(BaseModel):
    """告警信號"""
    alert_name: str
    severity: Severity
    source: str
    fired_at: datetime
    labels: dict[str, str] = {}
    annotations: dict[str, str] = {}
    fingerprint: str | None = None


class Incident(BaseModel):
    """事件資料結構"""
    incident_id: str
    status: IncidentStatus = IncidentStatus.INVESTIGATING
    severity: Severity = Severity.P2
    signals: list[Signal] = []
    affected_services: list[str] = []
    proposal_ids: list[UUID] = []
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)
    resolved_at: datetime | None = None
    closed_at: datetime | None = None


class IIncidentProcessor(ABC):
    """
    事件處理器介面

    職責:
    1. 聚合相關告警到同一 Incident
    2. 分析爆炸半徑 (透過 GraphRAG)
    3. 雙層持久化 (Working + Episodic Memory)

    使用方式:
        class MyIncidentProcessor(IIncidentProcessor):
            async def process_signal(self, signal_data: dict) -> Incident | None:
                # 實作邏輯
                pass
    """

    @abstractmethod
    async def process_signal(
        self,
        signal_data: dict[str, Any],
    ) -> Incident | None:
        """
        處理告警信號

        Args:
            signal_data: 告警資料 (來自 Redis Streams)

        Returns:
            Incident | None: 處理後的事件 (可能是新建或聚合)
        """
        ...

    @abstractmethod
    async def get_incident(
        self,
        incident_id: str,
    ) -> Incident | None:
        """
        取得事件

        Args:
            incident_id: 事件 ID

        Returns:
            Incident | None
        """
        ...

    @abstractmethod
    async def update_status(
        self,
        incident_id: str,
        status: IncidentStatus,
    ) -> bool:
        """
        更新事件狀態

        Args:
            incident_id: 事件 ID
            status: 新狀態

        Returns:
            bool: 是否成功
        """
        ...
