from typing import Annotated
from pydantic import BaseModel, ConfigDict, Field, SkipValidation, computed_field
from litestar.datastructures import UploadFile
from advanced_alchemy.utils.text import slugify


class LibraryCreate(BaseModel):
    name: Annotated[str, Field(min_length=1)]
    root_path: str
    path_template: str | None = "{author}/{title}"
    description: str | None = None
    icon: str = "library"
    read_only: bool = False

    @computed_field
    @property
    def slug(self) -> str:
        return slugify(self.name)


class LibraryRead(BaseModel):
    id: int
    name: str
    root_path: str
    path_template: str
    description: str | None
    icon: str
    read_only: bool
    total: int | None = None


class CalibreArchiveUpload(BaseModel):
    """
    A zipped Calibre library.

    The only way in through the API: a desktop Calibre install is usually not on the
    server at all. Importing from a path the server can already see is a server-side
    operation, and stays one — `litestar calibre-import` does that.
    """

    archive: Annotated[UploadFile, SkipValidation]
    allow_duplicates: bool = False

    model_config = ConfigDict(arbitrary_types_allowed=True)


class ImportFailureRead(BaseModel):
    """A book the import could not store."""

    model_config = ConfigDict(from_attributes=True)

    calibre_id: int
    title: str
    reason: str


class CalibreImportRead(BaseModel):
    """A running or finished import."""

    model_config = ConfigDict(from_attributes=True)

    id: str
    library_id: int
    source: str
    state: str

    total: int
    processed: int
    created: int
    skipped: int
    failed: int

    current_title: str | None = None
    failures: list[ImportFailureRead] = Field(default_factory=list)

    # A count, not the records. The library's duplicates screen is what shows them.
    possible_duplicates: int = 0

    # Set when the run itself broke, as opposed to individual books failing.
    error: str | None = None


class LibraryUpdate(BaseModel):
    name: str | None
    root_path: str | None
    path_template: str | None
    description: str | None
    icon: str | None
    read_only: bool | None
