"""Phase 11: Knowledge Management schemas — Playbooks + Lessons Learned."""

from datetime import datetime
from typing import List, Optional
from uuid import UUID

from pydantic import BaseModel, ConfigDict, field_validator

# ── Constants ─────────────────────────────────────────────────────────────────

VALID_PLAYBOOK_TYPES = ["attack", "detect", "investigate", "respond", "hunt"]
VALID_SEVERITIES     = ["critical", "high", "medium", "low", "info"]
VALID_ENTITY_TYPES   = ["test", "campaign", "attack_path", "manual"]


# ══════════════════════════════════════════════════════════════════════════════
# Playbook schemas
# ══════════════════════════════════════════════════════════════════════════════

class PlaybookCreate(BaseModel):
    technique_id:  UUID
    playbook_type: str
    title:         str
    content:       str = ""
    tools:         List[str] = []
    prerequisites: List[str] = []
    change_note:   Optional[str] = None

    @field_validator("playbook_type")
    @classmethod
    def validate_playbook_type(cls, v: str) -> str:
        if v not in VALID_PLAYBOOK_TYPES:
            raise ValueError(
                f"Invalid playbook_type '{v}'. Must be one of: {VALID_PLAYBOOK_TYPES}"
            )
        return v


class PlaybookUpdate(BaseModel):
    title:         Optional[str] = None
    content:       Optional[str] = None
    tools:         Optional[List[str]] = None
    prerequisites: Optional[List[str]] = None
    change_note:   Optional[str] = None


class PlaybookVersionOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id:            UUID
    playbook_id:   UUID
    version:       int
    title:         str
    content:       str
    tools:         List[str] = []
    prerequisites: List[str] = []
    changed_by:    Optional[UUID]
    change_note:   Optional[str]
    created_at:    datetime


class PlaybookOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id:            UUID
    technique_id:  UUID
    playbook_type: str
    title:         str
    content:       str
    version:       int
    tools:         List[str] = []
    prerequisites: List[str] = []
    created_by:    Optional[UUID]
    updated_by:    Optional[UUID]
    created_at:    datetime
    updated_at:    datetime
    is_active:     bool


# ══════════════════════════════════════════════════════════════════════════════
# Lesson Learned schemas
# ══════════════════════════════════════════════════════════════════════════════

class LessonLearnedCreate(BaseModel):
    title:         str
    what_happened: str
    root_cause:    str
    fix_applied:   Optional[str] = None
    severity:      str = "medium"
    entity_type:   str = "manual"
    entity_id:     Optional[UUID] = None
    technique_ids: List[str] = []
    tags:          List[str] = []

    @field_validator("severity")
    @classmethod
    def validate_severity(cls, v: str) -> str:
        if v not in VALID_SEVERITIES:
            raise ValueError(
                f"Invalid severity '{v}'. Must be one of: {VALID_SEVERITIES}"
            )
        return v

    @field_validator("entity_type")
    @classmethod
    def validate_entity_type(cls, v: str) -> str:
        if v not in VALID_ENTITY_TYPES:
            raise ValueError(
                f"Invalid entity_type '{v}'. Must be one of: {VALID_ENTITY_TYPES}"
            )
        return v


class LessonLearnedUpdate(BaseModel):
    title:         Optional[str] = None
    what_happened: Optional[str] = None
    root_cause:    Optional[str] = None
    fix_applied:   Optional[str] = None
    severity:      Optional[str] = None
    technique_ids: Optional[List[str]] = None
    tags:          Optional[List[str]] = None

    @field_validator("severity")
    @classmethod
    def validate_severity(cls, v: Optional[str]) -> Optional[str]:
        if v is not None and v not in VALID_SEVERITIES:
            raise ValueError(
                f"Invalid severity '{v}'. Must be one of: {VALID_SEVERITIES}"
            )
        return v


class LessonLearnedOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id:            UUID
    title:         str
    what_happened: str
    root_cause:    str
    fix_applied:   Optional[str]
    severity:      str
    entity_type:   str
    entity_id:     Optional[UUID]
    technique_ids: List[str] = []
    tags:          List[str] = []
    created_by:    Optional[UUID]
    created_at:    datetime
    updated_at:    datetime
    is_active:     bool
