"""
API request/response models.
"""

from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Any
from datetime import datetime

from aphub_sdk.schemas.agent import Agent, AgentSummary, AgentVersion
from aphub_sdk.schemas.skill import Skill, SkillSummary, SkillVersion
from aphub_sdk.schemas.manifest import AgentManifestV1
from aphub_sdk.schemas.skill_manifest import SkillManifestV1
from aphub_sdk.schemas.constants import DEFAULT_PAGE_SIZE


# =============================================================================
# Push API
# =============================================================================

class PushRequest(BaseModel):
    """Request to push an agent."""
    
    manifest: AgentManifestV1 = Field(..., description="Agent manifest")
    tag: Optional[str] = Field("latest", description="Version tag")
    
    # Optional file info (if pushing with content)
    file_content: Optional[bytes] = Field(None, description="Agent package content")
    checksum: Optional[str] = Field(None, description="SHA256 checksum")


class PushResponse(BaseModel):
    """Response from push operation."""
    
    success: bool = Field(..., description="Whether push succeeded")
    agent_id: Optional[str] = Field(None, description="Agent ID")
    version_id: Optional[str] = Field(None, description="Version ID")
    name: str = Field(..., description="Agent name")
    version: str = Field(..., description="Version string")
    tag: Optional[str] = Field(None, description="Version tag")
    
    # Upload URL for large files
    upload_url: Optional[str] = Field(None, description="Pre-signed upload URL")
    
    message: Optional[str] = Field(None, description="Status message")
    created_at: Optional[datetime] = Field(None, description="Creation timestamp")


# =============================================================================
# Pull API
# =============================================================================

class PullRequest(BaseModel):
    """Request to pull an agent."""
    
    name: str = Field(..., description="Agent name")
    version: Optional[str] = Field(None, description="Specific version")
    tag: Optional[str] = Field("latest", description="Version tag")


class PullResponse(BaseModel):
    """Response from pull operation."""
    
    success: bool = Field(..., description="Whether pull succeeded")
    agent: Optional[Agent] = Field(None, description="Agent details")
    version: Optional[AgentVersion] = Field(None, description="Version details")
    manifest: Optional[AgentManifestV1] = Field(None, description="Agent manifest")
    
    # Download URL
    download_url: Optional[str] = Field(None, description="Download URL")
    
    message: Optional[str] = Field(None, description="Status message")


# =============================================================================
# Search API
# =============================================================================

class SearchRequest(BaseModel):
    """Request to search agents."""
    
    query: str = Field(..., description="Search query")
    
    # Filters
    framework: Optional[str] = Field(None, description="Filter by framework")
    capabilities: Optional[List[str]] = Field(None, description="Filter by capabilities")
    protocols: Optional[List[str]] = Field(None, description="Filter by protocols")
    verified_only: bool = Field(False, description="Only verified agents")
    
    # Pagination
    page: int = Field(1, ge=1, description="Page number")
    page_size: int = Field(DEFAULT_PAGE_SIZE, ge=1, le=100, description="Results per page")
    
    # Sorting
    sort_by: str = Field("relevance", description="Sort field")
    sort_order: str = Field("desc", description="Sort order: asc or desc")


class SearchResult(BaseModel):
    """Single search result."""
    
    agent: AgentSummary = Field(..., description="Agent summary")
    score: float = Field(0.0, description="Relevance score")
    highlights: Optional[Dict[str, List[str]]] = Field(None, description="Search highlights")


class SearchResponse(BaseModel):
    """Response from search operation."""
    
    success: bool = Field(True, description="Whether search succeeded")
    query: str = Field(..., description="Original query")
    
    # Results
    results: List[SearchResult] = Field(default_factory=list, description="Search results")
    total: int = Field(0, description="Total matching results")
    
    # Pagination info
    page: int = Field(1, description="Current page")
    page_size: int = Field(DEFAULT_PAGE_SIZE, description="Results per page")
    total_pages: int = Field(0, description="Total pages")
    
    # Facets for filtering
    facets: Optional[Dict[str, Dict[str, int]]] = Field(
        None, 
        description="Facet counts (e.g., framework counts)"
    )


# =============================================================================
# Common API Models
# =============================================================================

class PageInfo(BaseModel):
    """Pagination information."""
    
    page: int = Field(1, description="Current page")
    page_size: int = Field(DEFAULT_PAGE_SIZE, description="Items per page")
    total: int = Field(0, description="Total items")
    total_pages: int = Field(0, description="Total pages")
    has_next: bool = Field(False, description="Has next page")
    has_prev: bool = Field(False, description="Has previous page")


class ListResponse(BaseModel):
    """Generic list response."""

    success: bool = Field(True, description="Success flag")
    items: List[Any] = Field(default_factory=list, description="List items")
    page_info: PageInfo = Field(default_factory=PageInfo, description="Pagination info")


# =============================================================================
# Skill Push API
# =============================================================================

class SkillPushRequest(BaseModel):
    """Request to push a skill."""

    manifest: SkillManifestV1 = Field(..., description="Skill manifest")
    tag: Optional[str] = Field("latest", description="Version tag")

    file_content: Optional[bytes] = Field(None, description="Skill package content")
    checksum: Optional[str] = Field(None, description="SHA256 checksum")


class SkillPushResponse(BaseModel):
    """Response from skill push operation."""

    success: bool = Field(..., description="Whether push succeeded")
    skill_id: Optional[str] = Field(None, description="Skill ID")
    version_id: Optional[str] = Field(None, description="Version ID")
    name: str = Field(..., description="Skill name")
    version: str = Field(..., description="Version string")
    tag: Optional[str] = Field(None, description="Version tag")

    upload_url: Optional[str] = Field(None, description="Pre-signed upload URL")
    message: Optional[str] = Field(None, description="Status message")
    created_at: Optional[datetime] = Field(None, description="Creation timestamp")


# =============================================================================
# Skill Pull API
# =============================================================================

class SkillPullRequest(BaseModel):
    """Request to pull a skill."""

    name: str = Field(..., description="Skill name")
    version: Optional[str] = Field(None, description="Specific version")
    tag: Optional[str] = Field("latest", description="Version tag")


class SkillPullResponse(BaseModel):
    """Response from skill pull operation."""

    success: bool = Field(..., description="Whether pull succeeded")
    skill: Optional[Skill] = Field(None, description="Skill details")
    version: Optional[SkillVersion] = Field(None, description="Version details")
    manifest: Optional[SkillManifestV1] = Field(None, description="Skill manifest")

    download_url: Optional[str] = Field(None, description="Download URL")
    message: Optional[str] = Field(None, description="Status message")


# =============================================================================
# Skill Search API
# =============================================================================

class SkillSearchRequest(BaseModel):
    """Request to search skills."""

    query: str = Field(..., description="Search query")

    platforms: Optional[List[str]] = Field(None, description="Filter by platforms")
    verified_only: bool = Field(False, description="Only verified skills")

    page: int = Field(1, ge=1, description="Page number")
    page_size: int = Field(DEFAULT_PAGE_SIZE, ge=1, le=100, description="Results per page")

    sort_by: str = Field("relevance", description="Sort field")
    sort_order: str = Field("desc", description="Sort order: asc or desc")


class SkillSearchResult(BaseModel):
    """Single skill search result."""

    skill: SkillSummary = Field(..., description="Skill summary")
    score: float = Field(0.0, description="Relevance score")
    highlights: Optional[Dict[str, List[str]]] = Field(None, description="Search highlights")


class SkillSearchResponse(BaseModel):
    """Response from skill search operation."""

    success: bool = Field(True, description="Whether search succeeded")
    query: str = Field(..., description="Original query")

    results: List[SkillSearchResult] = Field(default_factory=list, description="Search results")
    total: int = Field(0, description="Total matching results")

    page: int = Field(1, description="Current page")
    page_size: int = Field(DEFAULT_PAGE_SIZE, description="Results per page")
    total_pages: int = Field(0, description="Total pages")
