from __future__ import annotations

from typing import Optional, List

from pydantic import BaseModel, Field, field_validator


class ExtractPaperMetaRequest(BaseModel):
    """Request schema for extracting paper metadata and persisting to DB."""
    conference_id: int = Field(..., description="Existing conference ID")

    filename: str = Field(..., description="关于paper的文件名")
    paper: str = Field(..., description="Paper content in Markdown format")


class AuthorMeta(BaseModel):
    name: str = Field(..., description="Author's full name")
    email: Optional[str] = Field("", description="Author's email address")
    address: Optional[str] = Field("", description="Author's mailing address")
    affiliation: Optional[str] = Field(
        "",
        description=(
            "Author's official institution or organization name. "
            "Must use the standardized and officially recognized name. "
            "For example, use 'University of California, Berkeley' instead of 'UC Berkeley'. "
            "Validation ensures the institution name exists in the official global institution registry."
        ),
    )

    affiliation_country: Optional[str] = Field(
        "",
        description=(
            "Official country name corresponding to the author's institution. "
            "Must use ISO 3166-1 English short name format (e.g., 'United States', 'United Kingdom'). "
            "Validation ensures the country exists in the official ISO country list."
        ),
    )

    affiliation_city: Optional[str] = Field(
        "",
        description=(
            "Official city name corresponding to the author's institution. "
            "Must use the official English name of the city (e.g., 'Beijing', 'San Francisco'). "
            "Validation ensures the city exists within the specified country using a verified city database."
        ),
    )


class AuthorInfo(BaseModel):
    first_author: Optional[AuthorMeta] = Field(None, description="Information of the first author")
    co_first_authors: List[AuthorMeta] = Field(default_factory=list, description="List of co-first authors")
    middle_authors: List[AuthorMeta] = Field(default_factory=list, description="List of middle authors")
    last_authors: List[AuthorMeta] = Field(default_factory=list, description="Information of the last author")
    corresponding_authors: List[AuthorMeta] = Field(default_factory=list, description="List of corresponding authors")


class PaperMeta(BaseModel):
    paper_title: str = Field(..., description="Title of the paper")
    author_info: AuthorInfo = Field(..., description="Detailed author information")
    abstract: str = Field("", description="Abstract of the paper")
    keywords: List[str] = Field(default_factory=list, description="List of keywords")
    topic: str = Field(..., description="Main topic of the paper")

    @property
    def all_authors(self) -> List[AuthorMeta]:
        first = [self.author_info.first_author] if self.author_info.first_author is not None else []
        return (first + self.author_info.co_first_authors + self.author_info.middle_authors +
                self.author_info.last_authors + self.author_info.corresponding_authors)


class DocSegment(BaseModel):
    content: str = Field(..., description="Segment content (text)")
    metadata: Optional[dict] = Field(default_factory=dict, description="Optional metadata for the segment")


class ExtractPaperMetaFromDocsRequest(BaseModel):
    """Request schema for extracting paper metadata from pre-parsed documents."""
    conference_id: int = Field(..., description="Existing conference ID")
    filename: str = Field(..., description="关于paper的文件名")
    documents: List[DocSegment] = Field(..., description="Parsed document segments with content and metadata")


class ExtractPaperMetaResponse(BaseModel):
    paper_id: int = Field(..., description="ID of the extracted paper")
    title: str = Field(..., description="Title of the paper")
    conference_id: int = Field(..., description="ID of the conference")
    author_ids: List[int] = Field(default_factory=list, description="List of author IDs")
    topic: Optional[str] = Field(None, description="Main topic of the paper")
    full_meta: PaperMeta
    """All extracted information of this paper."""