from datetime import datetime
from typing import Literal

from pydantic import BaseModel, ConfigDict, Field, HttpUrl, field_validator

DocumentType = Literal[
    "manual",
    "service_manual",
    "schematic",
    "alignment",
    "parts_list",
    "firmware",
    "datasheet",
    "service_bulletin",
    "other",
]
NoteType = Literal["repair", "known_fault", "alignment", "spare_part", "general"]
NoteSeverity = Literal["low", "medium", "high", "critical", ""]


def normalize_text(value: object) -> str:
    if value is None:
        return ""
    return str(value).strip()


def normalize_tags(value: object) -> list[str]:
    if value is None or value == "":
        return []
    if isinstance(value, str):
        parts = value.split(",")
    elif isinstance(value, list):
        parts = value
    else:
        parts = []
    seen: set[str] = set()
    tags: list[str] = []
    for part in parts:
        tag = str(part).strip()
        key = tag.lower()
        if tag and key not in seen:
            seen.add(key)
            tags.append(tag)
    return tags


class KnowledgeManufacturerBase(BaseModel):
    name: str = Field(min_length=2, max_length=160)
    website: HttpUrl | None = None
    notes: str = ""

    @field_validator("name", "notes", mode="before")
    @classmethod
    def normalize_text_fields(cls, value: object) -> str:
        return normalize_text(value)


class KnowledgeManufacturerCreate(KnowledgeManufacturerBase):
    pass


class KnowledgeManufacturerUpdate(KnowledgeManufacturerBase):
    pass


class KnowledgeManufacturerResponse(KnowledgeManufacturerBase):
    id: int
    slug: str
    website: str
    created_at: datetime
    updated_at: datetime

    model_config = ConfigDict(from_attributes=True)


class KnowledgeDeviceBase(BaseModel):
    manufacturer_id: int
    name: str = Field(min_length=2, max_length=180)
    model_number: str = Field(default="", max_length=120)
    device_type: str = Field(default="", max_length=80)
    frequency_range: str = Field(default="", max_length=120)
    production_year_from: int | None = Field(default=None, ge=1900, le=2100)
    production_year_to: int | None = Field(default=None, ge=1900, le=2100)
    notes: str = ""

    @field_validator("name", "model_number", "device_type", "frequency_range", "notes", mode="before")
    @classmethod
    def normalize_text_fields(cls, value: object) -> str:
        return normalize_text(value)


class KnowledgeDeviceCreate(KnowledgeDeviceBase):
    pass


class KnowledgeDeviceUpdate(KnowledgeDeviceBase):
    pass


class KnowledgeDeviceResponse(KnowledgeDeviceBase):
    id: int
    slug: str
    created_at: datetime
    updated_at: datetime
    manufacturer: KnowledgeManufacturerResponse

    model_config = ConfigDict(from_attributes=True)


class KnowledgeDocumentBase(BaseModel):
    manufacturer_id: int
    device_id: int | None = None
    title: str = Field(min_length=2, max_length=255)
    document_type: DocumentType
    language: str = Field(default="de", min_length=2, max_length=20)
    external_url: HttpUrl | None = None
    paperless_document_id: str = Field(default="", max_length=120)
    description: str = ""
    tags: list[str] = Field(default_factory=list)

    @field_validator("title", "language", "paperless_document_id", "description", mode="before")
    @classmethod
    def normalize_text_fields(cls, value: object) -> str:
        return normalize_text(value)

    @field_validator("tags", mode="before")
    @classmethod
    def normalize_tag_fields(cls, value: object) -> list[str]:
        return normalize_tags(value)


class KnowledgeDocumentCreate(KnowledgeDocumentBase):
    pass


class KnowledgeDocumentUpdate(KnowledgeDocumentBase):
    pass


class KnowledgeDocumentResponse(KnowledgeDocumentBase):
    id: int
    slug: str
    external_url: str
    file_name: str
    file_path: str
    mime_type: str
    file_size: int
    checksum_sha256: str
    created_at: datetime
    updated_at: datetime
    manufacturer: KnowledgeManufacturerResponse
    device: KnowledgeDeviceResponse | None = None

    model_config = ConfigDict(from_attributes=True)


class KnowledgeNoteBase(BaseModel):
    manufacturer_id: int | None = None
    device_id: int | None = None
    title: str = Field(min_length=2, max_length=255)
    content: str = Field(min_length=1)
    note_type: NoteType = "general"
    severity: NoteSeverity = ""
    tags: list[str] = Field(default_factory=list)

    @field_validator("title", "content", "severity", mode="before")
    @classmethod
    def normalize_text_fields(cls, value: object) -> str:
        return normalize_text(value)

    @field_validator("tags", mode="before")
    @classmethod
    def normalize_tag_fields(cls, value: object) -> list[str]:
        return normalize_tags(value)


class KnowledgeNoteCreate(KnowledgeNoteBase):
    pass


class KnowledgeNoteUpdate(KnowledgeNoteBase):
    pass


class KnowledgeNoteResponse(KnowledgeNoteBase):
    id: int
    created_at: datetime
    updated_at: datetime
    manufacturer: KnowledgeManufacturerResponse | None = None
    device: KnowledgeDeviceResponse | None = None

    model_config = ConfigDict(from_attributes=True)


class KnowledgeSearchResult(BaseModel):
    entity_type: str
    id: int
    title: str
    subtitle: str = ""
    href: str
