"""
Pydantic schemas for request/response validation.

Provides typed data structures for API endpoints.
"""
from pydantic import BaseModel, EmailStr, Field, ConfigDict
from typing import Optional, List, Dict
from datetime import datetime


# ===== Authentication Schemas =====

class LoginRequest(BaseModel):
    """Login request payload."""
    username: str = Field(..., min_length=3, max_length=64)
    password: str = Field(..., min_length=6, max_length=128)


class LoginResponse(BaseModel):
    """Login response payload."""
    access_token: str
    refresh_token: str
    token_type: str = "bearer"
    user: dict


class RefreshTokenRequest(BaseModel):
    """Refresh token request."""
    refresh_token: str


class TokenResponse(BaseModel):
    """Token response."""
    access_token: str
    token_type: str = "bearer"


# ===== User Schemas =====

class UserBase(BaseModel):
    """User base fields."""
    username: str
    email: Optional[str] = None
    country: Optional[str] = Field(None, max_length=2)
    real_name: Optional[str] = None


class UserCreate(UserBase):
    """User registration fields."""
    password: str = Field(..., min_length=8)
    
    model_config = ConfigDict(
        json_schema_extra={
            "example": {
                "username": "player123",
                "password": "securepassword123",
                "email": "player@example.com",
                "country": "US"
            }
        }
    )


class UserUpdate(BaseModel):
    """User update fields."""
    email: Optional[str] = None
    country: Optional[str] = None
    real_name: Optional[str] = None
    new_password: Optional[str] = Field(None, min_length=8, max_length=128)


class UserResponse(BaseModel):
    """User response payload."""
    id: int
    username: str
    email: Optional[str]
    country: Optional[str]
    real_name: Optional[str]
    privlevel: str
    vip_status: int
    is_active: bool
    is_banned: bool
    ban_reason: Optional[str]
    creation_date: datetime
    last_login: Optional[datetime]
    
    model_config = ConfigDict(from_attributes=True)


# ===== Deck Schemas =====

class DeckCreate(BaseModel):
    """Deck creation request."""
    name: str = Field(..., min_length=1, max_length=255)
    content: str = Field(..., min_length=1)
    folder_id: Optional[int] = None
    format: str = Field("native", pattern="^(native|plain)$")
    status: str = Field("DRAUGHT", pattern="^(DRAUGHT|FINAL)$")


class DeckUpdate(BaseModel):
    """Deck update request."""
    name: Optional[str] = None
    content: Optional[str] = None
    folder_id: Optional[int] = None
    status: Optional[str] = Field(None, pattern="^(DRAUGHT|FINAL)$")


class DeckResponse(BaseModel):
    """Deck response payload."""
    id: int
    name: str
    content: str
    format: str
    status: str
    folder_id: Optional[int]
    owner_id: int
    creation_date: datetime
    
    model_config = ConfigDict(from_attributes=True)


class FolderCreate(BaseModel):
    """Folder creation request."""
    name: str = Field(..., min_length=1, max_length=255)
    parent_id: Optional[int] = None


class FolderResponse(BaseModel):
    """Folder response payload."""
    id: int
    name: str
    parent_id: Optional[int]
    owner_id: int
    creation_date: datetime
    
    model_config = ConfigDict(from_attributes=True)


# ===== Game Schemas =====

class GameCreate(BaseModel):
    """Game creation request."""
    room_id: int
    game_type: Optional[str] = None
    description: Optional[str] = None
    password: Optional[str] = None


class GameResponse(BaseModel):
    """Game response payload."""
    id: int
    room_id: int
    game_type: Optional[str]
    description: Optional[str]
    with_password: bool
    max_players: int
    player_count: int
    started: bool
    creation_date: datetime
    
    model_config = ConfigDict(from_attributes=True)


# ===== Room Schemas =====

class RoomResponse(BaseModel):
    """Room response payload."""
    id: int
    name: str
    description: Optional[str]
    is_password_protected: bool
    game_types: List[str] = []
    player_count: int = 0
    creation_date: datetime
    
    model_config = ConfigDict(from_attributes=True)


# ===== Ban Schemas =====

class BanCreate(BaseModel):
    """Ban creation request."""
    user_id: int
    reason: str = Field(..., min_length=1, max_length=1000)
    expiration_time: Optional[datetime] = None


class BanResponse(BaseModel):
    """Ban response payload."""
    id: int
    user_id: int
    reason: str
    moderators: Optional[str]
    expiration_time: Optional[datetime]
    active: bool
    creation_date: datetime
    
    model_config = ConfigDict(from_attributes=True)


# ===== Auth Error Responses =====

class ErrorResponse(BaseModel):
    """Standard error response."""
    detail: str


class ValidationErrorResponse(BaseModel):
    """Validation error response."""
    detail: List[dict]  # Pydantic validation errors


# ===== Pagination Schemas =====

class PaginationParams(BaseModel):
    """Common pagination parameters."""
    page: int = Field(1, ge=1)
    page_size: int = Field(50, ge=1, le=100)


class PaginatedResponse(BaseModel):
    """Generic paginated response."""
    items: List[dict]
    total: int
    page: int
    page_size: int
    total_pages: int


# ===== Card Mirror Schemas =====

class CardMirrorResponse(BaseModel):
    """Mirrored card data for user decks."""
    id: int
    source_id: Optional[int]
    name: str
    mana_cost: Optional[str]
    type_line: Optional[str]
    oracle_text: Optional[str]
    power: Optional[str]
    toughness: Optional[str]
    rarity: Optional[str]
    layout: Optional[str]
    artist: Optional[str]
    flavor_text: Optional[str]
    numbers: Optional[str]
    identifiers: Optional[str]  # JSON string
    images: Optional[str]  # JSON string
    image: Optional[str]
    card_parts: Optional[str]
    keywords: Optional[str]
    legalities: Optional[str]  # JSON string
    set_code: Optional[str]
    set_name: Optional[str]
    synced_at: Optional[datetime]
    created_at: datetime
    
    model_config = ConfigDict(from_attributes=True)


class DeckCardLinkResponse(BaseModel):
    """Deck-card link response."""
    id: int
    deck_id: int
    card_id: int
    quantity: int
    zone: str
    card: CardMirrorResponse
    
    model_config = ConfigDict(from_attributes=True)


class DeckWithCardsResponse(BaseModel):
    """Deck response with card links."""
    id: int
    name: str
    content: str
    format: str
    status: str
    folder_id: Optional[int]
    owner_id: int
    creation_date: datetime
    card_links: List[DeckCardLinkResponse] = []
    
    model_config = ConfigDict(from_attributes=True)
