"""Data models for axm-bib — Paper, BibEntry, DownloadResult."""

from __future__ import annotations

from pydantic import BaseModel, Field

__all__ = ["BibEntry", "DownloadResult", "ExtractionResult", "FigureInfo", "Paper"]


class Paper(BaseModel):
    """Normalized paper metadata from any source.

    Attributes:
        title: Paper title.
        authors: List of author names (min 1).
        year: Publication year.
        doi: Digital Object Identifier.
        arxiv_id: arXiv identifier.
        abstract: Paper abstract text.
        venue: Conference/journal name.
        citation_count: Number of citations.
        open_access_pdf: URL to open-access PDF.
        source: Data source ("semantic_scholar" | "crossref").
    """

    title: str
    authors: list[str] = Field(min_length=1)
    year: int | None = None
    doi: str | None = None
    arxiv_id: str | None = None
    abstract: str | None = None
    venue: str | None = None
    citation_count: int | None = None
    open_access_pdf: str | None = None
    source: str


class BibEntry(BaseModel):
    """Parsed + normalized BibTeX entry.

    Attributes:
        key: Citation key (e.g. "smith2024deep").
        entry_type: BibTeX entry type ("article", "inproceedings", etc.).
        raw: Full raw BibTeX string.
        doi: DOI if available.
        title: Paper title.
        authors: List of author names.
        year: Publication year.
    """

    key: str
    entry_type: str
    raw: str
    doi: str | None = None
    title: str | None = None
    authors: list[str] = Field(default_factory=list)
    year: int | None = None


class DownloadResult(BaseModel):
    """Result of a PDF download operation.

    Attributes:
        doi: DOI of the downloaded paper.
        path: Absolute path to the saved PDF file.
        size_bytes: File size in bytes.
        is_open_access: Whether the paper is open access.
        paper_dir: Absolute path to the paper folder.
        bibtex_path: Absolute path to paper.bib.
        extraction: Extraction result (markdown + figures metadata).
    """

    doi: str
    path: str
    size_bytes: int
    is_open_access: bool
    paper_dir: str | None = None
    bibtex_path: str | None = None
    extraction: ExtractionResult | None = None


class FigureInfo(BaseModel):
    """Metadata for an extracted figure.

    Attributes:
        index: 1-based sequential number.
        filename: Output filename (e.g. "fig_001.png").
        page: 0-based page number from PDF.
        width: Pixel width.
        height: Pixel height.
        xref: PDF internal cross-reference id.
    """

    index: int
    filename: str
    page: int
    width: int
    height: int
    xref: int


class ExtractionResult(BaseModel):
    """Result of a PDF extraction operation.

    Attributes:
        source_pdf: Absolute path to input PDF.
        output_dir: Absolute path to output folder.
        markdown_path: Absolute path to content.md.
        figures: Extracted figures metadata.
        page_count: Total pages in PDF.
        char_count: Total characters in markdown.
    """

    source_pdf: str
    output_dir: str
    markdown_path: str
    figures: list[FigureInfo] = Field(default_factory=list)
    page_count: int
    char_count: int
