"""
Knowledge Base Models
=====================
Phase KB-1: 知識庫資料模型

兩層架構:
- KnowledgeEntry: 知識條目 (incident_case / runbook / best_practice / postmortem)
- Playbook: 獨立系統，透過 related_playbook_id 關聯

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

遵循 leWOOOgo 積木化原則:
- Pydantic BaseModel 定義
- PostgreSQL Episodic Memory
"""

from datetime import datetime
from enum import Enum

from pydantic import BaseModel, Field

from src.utils.timezone import now_taipei


# =============================================================================
# Enums
# =============================================================================

class EntryType(str, Enum):
    """知識條目類型"""
    INCIDENT_CASE = "incident_case"      # AI 從 Incident 萃取的案例分析
    RUNBOOK = "runbook"                  # 手動建立的操作手冊
    BEST_PRACTICE = "best_practice"      # 最佳實踐文章
    POSTMORTEM = "postmortem"            # 事後分析報告
    # 2026-04-04 ogt: Phase 25 P1 — Knowledge Auto-Harvesting 新增類型
    AUTO_RUNBOOK = "auto_runbook"        # Nemotron 自動生成的 Runbook（DRAFT 待人工審核）
    ANTI_PATTERN = "anti_pattern"        # 修復失敗案例（直接 PUBLISHED，阻斷後續重蹈覆轍）


class EntrySource(str, Enum):
    """知識來源"""
    AI_EXTRACTED = "ai_extracted"        # AI 自動萃取
    HUMAN = "human"                      # 人工建立


class EntryStatus(str, Enum):
    """知識條目狀態"""
    DRAFT = "draft"                      # 草稿
    REVIEW = "review"                    # 審核中
    APPROVED = "approved"                # 已批准
    ARCHIVED = "archived"                # 已封存
    # 2026-04-04 Claude Code: Phase 25 P1 — ANTI_PATTERN 直接發布，無需審核
    PUBLISHED = "published"              # 已發布（ANTI_PATTERN 用，無需人工審核）


# =============================================================================
# Pydantic Models
# =============================================================================

class KnowledgeEntryCreate(BaseModel):
    """建立知識條目 Request"""
    title: str = Field(..., min_length=1, max_length=255)
    content: str = Field(..., min_length=1)
    entry_type: EntryType
    category: str = Field(..., min_length=1, max_length=100)
    tags: list[str] = Field(default_factory=list)
    source: EntrySource = EntrySource.HUMAN
    status: EntryStatus = EntryStatus.DRAFT
    related_incident_id: str | None = None
    related_playbook_id: str | None = None
    # P1-1 2026-04-28 ogt + Claude Sonnet 4.6: M4 補反查鏈 — approval → KM 關聯
    # phase26_incident_km_integration.sql 已建立 related_approval_id 欄位與 partial index
    related_approval_id: str | None = None
    # P1-1 M3 2026-04-28 ogt + Claude Sonnet 4.6: 冪等 key（與 related_incident_id 組合）
    # migration: p1_1_km_idempotent_path_type.sql
    path_type: str | None = None
    # 2026-04-04 ogt: Phase 25 P1 — Anti-Pattern 閉環用症狀 hash
    symptoms_hash: str | None = None
    created_by: str | None = None


class KnowledgeEntryUpdate(BaseModel):
    """更新知識條目 Request"""
    title: str | None = None
    content: str | None = None
    entry_type: EntryType | None = None
    category: str | None = None
    tags: list[str] | None = None
    status: EntryStatus | None = None


class KnowledgeEntry(BaseModel):
    """知識條目完整模型"""
    id: str
    title: str
    content: str
    entry_type: EntryType
    category: str
    tags: list[str] = Field(default_factory=list)
    source: EntrySource
    status: EntryStatus = EntryStatus.DRAFT
    related_incident_id: str | None = None
    related_playbook_id: str | None = None
    # P1-1 2026-04-28 ogt + Claude Sonnet 4.6: M4 補反查鏈
    related_approval_id: str | None = None
    # P1-1 M3 2026-04-28 ogt + Claude Sonnet 4.6: 冪等 key
    path_type: str | None = None
    # 2026-04-04 ogt: Phase 25 P1 — Anti-Pattern 閉環攔截用的症狀 hash（SymptomPattern.compute_hash()）
    symptoms_hash: str | None = None
    view_count: int = 0
    created_by: str | None = None
    created_at: datetime = Field(default_factory=now_taipei)
    updated_at: datetime = Field(default_factory=now_taipei)

    model_config = {"from_attributes": True}


class CategoryCount(BaseModel):
    """分類統計"""
    category: str
    count: int


class KnowledgeListResponse(BaseModel):
    """列表回應"""
    items: list[KnowledgeEntry]
    total: int
    categories: list[CategoryCount] = Field(default_factory=list)
