"""
Incident Type Converter - 跨套件 Incident 型別轉換
====================================================
ADR-046: BrainIncident (lewooogo-brain) ↔ LocalIncident (apps/api) 轉換層

設計原則:
- BrainIncident: lewooogo-brain 套件的精簡型別 (無 AWOOOI 擴展欄位)
- LocalIncident: apps/api 的完整型別 (含 decision_chain, outcome 等稽核欄位)
- 兩者保持套件邊界，互不依賴，透過 Converter 顯式轉換

轉換方向:
  brain→local: 引擎輸出 → 本地服務消費 (IncidentMemoryAdapter, signal_worker)
  local→brain: 本地資料 → 引擎輸入 (儲存到 DualIncidentMemory)

版本: v1.0
建立: 2026-04-01 (台北時區)
建立者: Claude Code (ADR-046 Phase R-R3 Sprint)
"""

from typing import Any
from uuid import uuid4

import structlog

from src.models.incident import (
    Incident,
    IncidentStatus,
    Severity,
    Signal,
)

logger = structlog.get_logger(__name__)


def brain_to_local(brain_incident: Any) -> Incident:
    """
    BrainIncident → LocalIncident 轉換

    ADR-046: 跨套件邊界時呼叫，將 lewooogo-brain 引擎輸出轉為本地型別。

    欄位對應:
    - incident_id, status, severity, signals, affected_services,
      proposal_ids, created_at, updated_at, resolved_at, closed_at → 直接對應
    - decision_chain, outcome, frequency_stats → None (BrainIncident 無此欄位)
    - ttl_days, persisted_to_pg, vectorized → 使用預設值

    BrainIncidentStatus.ESCALATED 不存在 → 本地 ESCALATED 需 local_to_brain 時處理
    """
    try:
        from lewooogo_brain.interfaces.incident_processor import (
            IncidentStatus as BrainIncidentStatus,
            Severity as BrainSeverity,
        )

        # --- 狀態轉換 ---
        try:
            local_status = IncidentStatus(brain_incident.status.value)
        except ValueError:
            # BrainIncident 無 ESCALATED；理論上不應發生，記錄並降級
            logger.warning(
                "brain_to_local_unknown_status",
                status=brain_incident.status,
                incident_id=brain_incident.incident_id,
            )
            local_status = IncidentStatus.INVESTIGATING

        # --- 嚴重度轉換 ---
        try:
            local_severity = Severity(brain_incident.severity.value)
        except ValueError:
            logger.warning(
                "brain_to_local_unknown_severity",
                severity=brain_incident.severity,
                incident_id=brain_incident.incident_id,
            )
            local_severity = Severity.P2

        # --- Signal 轉換 ---
        local_signals = []
        for brain_signal in brain_incident.signals:
            try:
                sig_severity = Severity(brain_signal.severity.value)
            except ValueError:
                sig_severity = Severity.P2

            # BrainSignal.source 是 str，LocalSignal.source 是 Literal
            # 使用 getattr 確保不因 BrainSignal 欄位增減而崩潰
            source = getattr(brain_signal, "source", "alertmanager")
            valid_sources = {"prometheus", "signoz", "alertmanager", "manual", "telegram"}
            if source not in valid_sources:
                source = "alertmanager"

            local_signals.append(
                Signal(
                    signal_id=str(uuid4())[:8],  # BrainSignal 無 signal_id，自動生成
                    alert_name=brain_signal.alert_name,
                    severity=sig_severity,
                    source=source,
                    fired_at=brain_signal.fired_at,
                    resolved_at=getattr(brain_signal, "resolved_at", None),
                    labels=getattr(brain_signal, "labels", {}),
                    annotations=getattr(brain_signal, "annotations", {}),
                    fingerprint=getattr(brain_signal, "fingerprint", None),
                )
            )

        return Incident(
            incident_id=brain_incident.incident_id,
            status=local_status,
            severity=local_severity,
            signals=local_signals,
            affected_services=brain_incident.affected_services or [],
            decision_chain=None,   # BrainIncident 無此欄位
            proposal_ids=list(brain_incident.proposal_ids or []),
            outcome=None,          # BrainIncident 無此欄位
            frequency_stats=None,  # BrainIncident 無此欄位
            created_at=brain_incident.created_at,
            updated_at=brain_incident.updated_at,
            resolved_at=brain_incident.resolved_at,
            closed_at=brain_incident.closed_at,
            ttl_days=7,
            persisted_to_pg=False,
            vectorized=False,
        )

    except Exception as e:
        logger.error(
            "brain_to_local_conversion_failed",
            incident_id=getattr(brain_incident, "incident_id", "unknown"),
            error=str(e),
        )
        raise


def local_to_brain(local_incident: Incident) -> Any:
    """
    LocalIncident → BrainIncident 轉換

    ADR-046: 將本地完整 Incident 轉換為 lewooogo-brain 精簡格式，
    供 DualIncidentMemory 儲存或 IncidentEngine 消費。

    LocalIncidentStatus.ESCALATED 無對應 BrainStatus → 映射為 MITIGATING
    (升級中的事件在 brain 視角仍屬「處置中」)

    local-only 欄位 (decision_chain, outcome, frequency_stats 等) 在轉換後遺失，
    請勿用 local_to_brain → brain_to_local 做 round-trip。
    """
    try:
        from lewooogo_brain.interfaces.incident_processor import (
            Incident as BrainIncident,
            IncidentStatus as BrainIncidentStatus,
            Severity as BrainSeverity,
            Signal as BrainSignal,
        )

        # --- 狀態轉換 ---
        _status_map = {
            "investigating": "investigating",
            "mitigating": "mitigating",
            "resolved": "resolved",
            "closed": "closed",
            "escalated": "mitigating",  # ADR-046: ESCALATED → MITIGATING (brain 無 ESCALATED)
        }
        brain_status_value = _status_map.get(local_incident.status.value, "investigating")
        brain_status = BrainIncidentStatus(brain_status_value)

        # --- 嚴重度轉換 (1:1 對應) ---
        brain_severity = BrainSeverity(local_incident.severity.value)

        # --- Signal 轉換 ---
        brain_signals = []
        for local_signal in local_incident.signals:
            brain_signals.append(
                BrainSignal(
                    alert_name=local_signal.alert_name,
                    severity=BrainSeverity(local_signal.severity.value),
                    source=local_signal.source,  # str 相容
                    fired_at=local_signal.fired_at,
                    labels=local_signal.labels,
                    annotations=local_signal.annotations,
                    fingerprint=local_signal.fingerprint,
                    # signal_id 和 resolved_at 是 LocalSignal 擴展欄位，BrainSignal 不存在
                )
            )

        return BrainIncident(
            incident_id=local_incident.incident_id,
            status=brain_status,
            severity=brain_severity,
            signals=brain_signals,
            affected_services=local_incident.affected_services,
            proposal_ids=local_incident.proposal_ids,
            created_at=local_incident.created_at,
            updated_at=local_incident.updated_at,
            resolved_at=local_incident.resolved_at,
            closed_at=local_incident.closed_at,
        )

    except Exception as e:
        logger.error(
            "local_to_brain_conversion_failed",
            incident_id=local_incident.incident_id,
            error=str(e),
        )
        raise
