"""
Repository Interfaces - Protocol 定義
======================================
Phase 16 R3: Repository 層 Protocol 介面

設計原則:
- 使用 Python Protocol 實現 DI
- Service 層只依賴 Protocol，不依賴具體實作
- 便於測試 (可注入 Mock Repository)

版本: v1.0
建立: 2026-03-26 (台北時區)
建立者: Claude Code (Phase 16 架構重構)
"""

from datetime import datetime
from typing import Protocol, runtime_checkable
from uuid import UUID

from src.models.approval import ApprovalRequest, ApprovalRequestCreate, ApprovalStatus
from src.models.incident import Incident
from src.models.knowledge import (
    EntryStatus,
    EntryType,
    KnowledgeEntry,
    KnowledgeEntryCreate,
)
from src.models.playbook import (
    Playbook,
    PlaybookStatus,
    SymptomPattern,
)


@runtime_checkable
class IApprovalRepository(Protocol):
    """
    Approval Repository Protocol

    職責: ApprovalRecord CRUD 操作
    實作: ApprovalDBRepository (PostgreSQL)
    """

    async def create(self, data: dict) -> ApprovalRequest:
        """
        建立新的 Approval

        Phase 22 P2: 簽名修正為 dict (與實作一致)
        2026-03-31 Claude Code (首席架構師 P2 修復)

        Args:
            data: ApprovalRecord 建立資料 dict

        Returns:
            ApprovalRequest
        """
        ...

    async def get_by_id(self, approval_id: UUID) -> ApprovalRequest | None:
        """根據 ID 取得 Approval"""
        ...

    async def get_pending(self) -> list[ApprovalRequest]:
        """取得所有待審核的 Approval"""
        ...

    async def update_status(
        self,
        approval_id: UUID,
        status: ApprovalStatus,
        actor: str | None = None,
    ) -> ApprovalRequest | None:
        """更新 Approval 狀態"""
        ...

    async def add_signature(
        self,
        approval_id: UUID,
        signer: str,
        decision: str,
        comment: str | None = None,
    ) -> ApprovalRequest | None:
        """新增簽核"""
        ...

    async def find_by_fingerprint(
        self,
        fingerprint: str,
    ) -> ApprovalRequest | None:
        """
        根據指紋查找 Approval (告警收斂用)

        Phase 22 P2: 補齊缺失 Protocol 方法
        2026-03-31 Claude Code (首席架構師 P2 修復)
        """
        ...

    async def increment_hit_count(
        self,
        approval_id: UUID,
    ) -> ApprovalRequest | None:
        """
        增加 hit_count (告警收斂用)

        Phase 22 P2: 補齊缺失 Protocol 方法
        2026-03-31 Claude Code (首席架構師 P2 修復)
        """
        ...


@runtime_checkable
class IIncidentRepository(Protocol):
    """
    Incident Repository Protocol

    職責: IncidentRecord CRUD 操作
    實作: IncidentDBRepository (PostgreSQL)
    """

    async def create(self, incident: Incident) -> Incident:
        """建立新的 Incident"""
        ...

    async def get_by_id(self, incident_id: str) -> Incident | None:
        """根據 ID 取得 Incident"""
        ...

    async def get_active(self) -> list[Incident]:
        """取得所有活躍的 Incident"""
        ...

    async def update(self, incident: Incident) -> Incident | None:
        """更新 Incident"""
        ...

    async def upsert(self, incident: Incident) -> bool:
        """Upsert Incident (存在則更新，不存在則建立)"""
        ...


@runtime_checkable
class ITimelineRepository(Protocol):
    """
    Timeline Repository Protocol

    職責: TimelineEvent CRUD 操作
    實作: TimelineDBRepository (PostgreSQL)
    """

    async def add_event(
        self,
        approval_id: UUID,
        event_type: str,
        actor: str,
        details: dict | None = None,
    ) -> bool:
        """新增 Timeline 事件"""
        ...

    async def get_events(
        self,
        approval_id: UUID,
        limit: int = 100,
    ) -> list[dict]:
        """取得 Approval 的 Timeline 事件"""
        ...

    async def get_recent_events(
        self,
        limit: int = 50,
        hours: int = 24,
    ) -> list[dict]:
        """取得最近的 Timeline 事件"""
        ...


@runtime_checkable
class IMetricsRepository(Protocol):
    """
    Metrics Repository Protocol

    職責: Metrics 相關 DB 查詢 (AI Success Rate)
    實作: MetricsDBRepository (PostgreSQL)

    版本: v1.0
    建立: 2026-03-26 (台北時區)
    建立者: Claude Code (Phase 17 技術債修復)
    """

    async def get_ai_success_rate(
        self,
        hours: int = 24,
    ) -> tuple[float, int, int]:
        """
        計算 AI 提案成功執行率

        Args:
            hours: 統計時間範圍 (小時)

        Returns:
            (success_rate_percent, executed_count, total_count)
        """
        ...

    async def get_ai_success_trend(
        self,
        hours: int = 24,
        points: int = 10,
    ) -> list[float]:
        """
        取得 AI 成功率趨勢 (Sparkline 用)

        Args:
            hours: 統計時間範圍 (小時)
            points: 趨勢點數量

        Returns:
            list[float]: 每小時成功率列表 (由舊到新)
        """
        ...


@runtime_checkable
class IKnowledgeRepository(Protocol):
    """
    Knowledge Repository Protocol

    職責: KnowledgeEntry CRUD 操作 (PostgreSQL)
    實作: KnowledgeDBRepository

    建立: 2026-04-02 (台北時區)
    建立者: Claude Code (Knowledge Base Phase 1)
    """

    async def create(self, data: KnowledgeEntryCreate) -> KnowledgeEntry:
        """建立知識條目"""
        ...

    async def get_by_id(self, entry_id: str) -> KnowledgeEntry | None:
        """根據 ID 取得知識條目"""
        ...

    async def update(self, entry_id: str, data: dict) -> KnowledgeEntry | None:
        """更新知識條目"""
        ...

    async def delete(self, entry_id: str) -> bool:
        """軟刪除知識條目 (status → archived)"""
        ...

    async def list_entries(
        self,
        category: str | None = None,
        entry_type: EntryType | None = None,
        status: EntryStatus | None = None,
        tags: list[str] | None = None,
        q: str | None = None,
        limit: int = 20,
        offset: int = 0,
    ) -> tuple[list[KnowledgeEntry], int]:
        """列出知識條目 (支援篩選)"""
        ...

    async def get_categories(self) -> list[tuple[str, int]]:
        """取得分類統計 [(category, count)]"""
        ...

    async def search(self, query: str, limit: int = 20) -> list[KnowledgeEntry]:
        """關鍵字搜尋 (title + content + tags)"""
        ...

    async def increment_view_count(self, entry_id: str) -> bool:
        """view_count +1"""
        ...

    async def save_embedding(self, entry_id: str, embedding: list[float]) -> bool:
        """儲存向量 embedding (1024 維, pgvector, bge-m3:latest)"""
        ...

    async def semantic_search(
        self,
        query_embedding: list[float],
        limit: int = 10,
        threshold: float = 0.5,
    ) -> list[tuple["KnowledgeEntry", float]]:
        """語意搜尋 — cosine similarity, 回傳 (entry, score) 降序"""
        ...

    async def list_unembedded_entries(
        self,
    ) -> list[tuple[str, str, str]]:
        """列出尚未產生 embedding 的條目 [(id, title, content)]"""
        ...


@runtime_checkable
class IPlaybookRepository(Protocol):
    """
    Playbook Repository Protocol

    職責: Playbook CRUD 操作 (PostgreSQL + Redis 雙層)
    實作: PlaybookRepository

    版本: v1.0
    建立: 2026-03-26 (台北時區)
    建立者: Claude Code (#7 Playbook 萃取)
    """

    async def create(self, playbook: Playbook) -> Playbook:
        """建立新的 Playbook"""
        ...

    async def get_by_id(self, playbook_id: str) -> Playbook | None:
        """根據 ID 取得 Playbook"""
        ...

    async def update(self, playbook: Playbook) -> Playbook | None:
        """更新 Playbook"""
        ...

    async def delete(self, playbook_id: str) -> bool:
        """刪除 Playbook (軟刪除 → DEPRECATED)"""
        ...

    async def list_playbooks(
        self,
        status: PlaybookStatus | None = None,
        tags: list[str] | None = None,
        limit: int = 20,
        offset: int = 0,
    ) -> tuple[list[Playbook], int]:
        """
        列出 Playbooks

        Returns:
            (items, total_count)
        """
        ...

    async def find_by_symptoms(
        self,
        symptoms: SymptomPattern,
        top_k: int = 5,
        min_similarity: float = 0.5,
    ) -> list[tuple[Playbook, float]]:
        """
        根據症狀模式找相似 Playbook

        Returns:
            list[(Playbook, similarity_score)]
        """
        ...

    async def update_stats(
        self,
        playbook_id: str,
        success: bool,
    ) -> bool:
        """更新執行統計"""
        ...

    async def find_by_source_incident(
        self,
        incident_id: str,
    ) -> list[Playbook]:
        """
        根據來源 Incident ID 找 Playbook

        2026-03-30 Claude Code: Learning Service 信心度調整用
        尋找 source_incident_ids 包含此 incident_id 的 Playbooks
        """
        ...

    async def adjust_confidence(
        self,
        playbook_id: str,
        delta: float,
        reason: str,
    ) -> Playbook | None:
        """
        調整 Playbook 信心度

        2026-03-30 Claude Code: Learning Service 信心度調整用

        Args:
            playbook_id: Playbook ID
            delta: 調整量 (+/- 0.0~1.0)
            reason: 調整原因 (審計用)

        Returns:
            更新後的 Playbook，或 None (如果不存在)
        """
        ...


@runtime_checkable
class ILearningRepository(Protocol):
    """
    Learning Repository Protocol

    職責: 學習數據持久化 (Redis)
    實作: LearningRepository

    版本: v1.0
    建立: 2026-03-29 (台北時區)
    建立者: Claude Code (Phase D-G P0 修正)

    設計原則:
    - Service 層不直接存取 Redis
    - 透過 Repository 進行資料存取
    - 符合 leWOOOgo 積木化原則
    """

    async def record_repair(
        self,
        anomaly_key: str,
        repair_action: str,
        success: bool,
        root_cause: str | None = None,
        fix_description: str | None = None,
        execution_time_seconds: float | None = None,
    ) -> bool:
        """記錄修復結果"""
        ...

    async def get_repair_stats(
        self,
        anomaly_key: str,
        repair_action: str,
    ) -> dict:
        """取得修復統計 (成功率、執行次數)"""
        ...

    async def get_all_repair_stats(
        self,
        anomaly_key: str,
    ) -> dict[str, dict]:
        """取得所有修復動作的統計"""
        ...

    async def get_repair_history(
        self,
        anomaly_key: str,
        repair_action: str,
        limit: int = 20,
    ) -> list[dict]:
        """取得修復歷史記錄"""
        ...

    async def get_learning_summary(
        self,
        anomaly_key: str,
    ) -> dict:
        """取得學習摘要"""
        ...


@runtime_checkable
class IEmbeddingCacheRepository(Protocol):
    """
    Embedding Cache Repository Protocol

    職責: Playbook 向量快取 (Redis)
    實作: EmbeddingCacheRepository

    2026-03-27 ogt: 模組化改造 (P1 違規修復)
    """

    async def store(
        self,
        playbook_id: str,
        embedding: list[float],
        metadata: dict | None = None,
    ) -> bool:
        """儲存 Playbook 向量"""
        ...

    async def get(self, playbook_id: str) -> list[float] | None:
        """取得 Playbook 向量"""
        ...

    async def get_all(self) -> dict[str, list[float]]:
        """取得所有 Playbook 向量"""
        ...

    async def remove(self, playbook_id: str) -> bool:
        """移除 Playbook 向量"""
        ...


@runtime_checkable
class IK8sRepository(Protocol):
    """
    K8s Repository Protocol

    職責: K8s API 操作 (Pods/Deployments/Events)
    實作: K8sRepository (kubernetes_asyncio)

    版本: v1.0
    建立: 2026-03-30 (台北時區)
    建立者: Claude Code (首席架構師 P1 改進)

    設計原則:
    - Service 層不直接呼叫 kubernetes_asyncio
    - 透過 Repository 進行 K8s 操作
    - 符合 leWOOOgo 積木化原則
    """

    async def list_pods(
        self,
        namespace: str = "awoooi",
    ) -> list[dict]:
        """
        列出 Namespace 下的 Pods

        Returns:
            list[{name, phase, ready, restarts, age}]
        """
        ...

    async def list_deployments(
        self,
        namespace: str = "awoooi",
    ) -> list[dict]:
        """
        列出 Namespace 下的 Deployments

        Returns:
            list[{name, ready_replicas, replicas, available}]
        """
        ...

    async def get_pod_status_summary(
        self,
        namespace: str = "awoooi",
    ) -> dict:
        """
        取得 Pod 狀態摘要

        Returns:
            {total, running, pending, failed, problem_pods: [...]}
        """
        ...

    async def is_available(self) -> bool:
        """
        檢查 K8s API 是否可用

        Returns:
            True 如果 K8s 連線正常
        """
        ...


# =============================================================================
# Phase 18: Failure Auto-Repair Loop Protocols
# =============================================================================
# 2026-03-31 Claude Code (統帥批准)
# =============================================================================


@runtime_checkable
class IFailureWatcher(Protocol):
    """
    Failure Watcher Protocol

    職責: 監聽失敗事件並觸發修復流程
    實作: FailureWatcherService

    版本: v1.0
    建立: 2026-03-31 (台北時區)
    建立者: Claude Code (Phase 18 失敗自動修復)
    """

    async def process_failure(
        self,
        audit_log_id: str,
        failure_data: dict,
    ) -> dict:
        """
        處理單一失敗事件

        Args:
            audit_log_id: AuditLog ID
            failure_data: 失敗詳情

        Returns:
            {
                "repair_attempted": bool,
                "repair_result": str | None,
                "risk_level": str,  # LOW/MEDIUM/CRITICAL
                "next_action": str,  # auto_repair/await_approval/escalate
            }
        """
        ...

    async def analyze_failure(
        self,
        error_message: str,
        operation_type: str,
        target_resource: str,
    ) -> dict:
        """
        AI 分析失敗原因

        Args:
            error_message: 錯誤訊息
            operation_type: 操作類型
            target_resource: 目標資源

        Returns:
            {
                "classification": str,  # TIMEOUT/K8S_ERROR/NETWORK_ERROR/PERMISSION_DENIED
                "root_cause": str,
                "suggested_repair": str,
                "risk_level": str,
                "confidence": float,
            }
        """
        ...

    async def execute_auto_repair(
        self,
        audit_log_id: str,
        repair_strategy: str,
        failure_data: dict | None = None,
    ) -> tuple[bool, str]:
        """
        執行自動修復 (僅限 LOW 風險)

        Phase 18.3: K8s Executor 整合
        2026-03-31 Claude Code (統帥批准)

        Args:
            audit_log_id: 原始失敗的 AuditLog ID
            repair_strategy: 修復策略
            failure_data: 失敗詳情 (含 target_resource, namespace)

        Returns:
            (success, result_message)
        """
        ...


@runtime_checkable
class ITrustRepository(Protocol):
    """
    Trust Repository Protocol

    職責: TrustRecord 持久化 (PostgreSQL)
    實作: TrustRepository

    ADR-088: TrustScoreManager 持久化層
    2026-04-17 ogt + Claude Sonnet 4.6（亞太）: Phase 4 信任持久化
    """

    async def upsert(
        self,
        action_pattern: str,
        score: int,
        total_approvals: int,
        total_rejections: int,
        last_approval_by: str | None = None,
        last_approval_at: datetime | None = None,
        last_rejection_by: str | None = None,
        last_rejection_at: datetime | None = None,
    ) -> bool:
        """INSERT or UPDATE trust record (upsert by action_pattern)"""
        ...

    async def load_all(self) -> list[dict]:
        """
        載入所有 trust records 供啟動 warm-up

        Returns:
            list[{action_pattern, score, total_approvals, total_rejections,
                  last_approval_by, last_approval_at, last_rejection_by, last_rejection_at}]
        """
        ...
