"""API extraction types."""

from enum import Enum

from pydantic import BaseModel, ConfigDict, Field


class HTTPMethod(str, Enum):
    """HTTP methods."""

    GET = "GET"
    POST = "POST"
    PUT = "PUT"
    PATCH = "PATCH"
    DELETE = "DELETE"
    HEAD = "HEAD"
    OPTIONS = "OPTIONS"


class AuthType(str, Enum):
    """Authentication mechanisms."""

    NONE = "none"
    BEARER = "bearer"
    BASIC = "basic"
    API_KEY = "api_key"
    OAUTH = "oauth"
    CUSTOM = "custom"


class HeaderDefinition(BaseModel):
    """Describes an HTTP header."""

    model_config = ConfigDict(populate_by_name=True)

    name: str
    value: str | None = None  # Static value if known
    source: str | None = None  # Where value comes from (e.g., "env", "state", "constant")
    description: str | None = None
    is_required: bool = Field(alias="isRequired")


class PayloadField(BaseModel):
    """Describes a field in request/response payload."""

    model_config = ConfigDict(populate_by_name=True)

    name: str
    type: str  # TypeScript type
    required: bool
    description: str | None = None
    children: list["PayloadField"] | None = None  # For nested objects


class PayloadDefinition(BaseModel):
    """Describes request or response payload."""

    model_config = ConfigDict(populate_by_name=True)

    content_type: str = Field(alias="contentType")  # e.g., "application/json"
    fields: list[PayloadField] | None = None
    is_array: bool = Field(default=False, alias="isArray")
    type_name: str | None = Field(default=None, alias="typeName")  # TypeScript interface name


class AuthDefinition(BaseModel):
    """Describes authentication configuration."""

    model_config = ConfigDict(populate_by_name=True)

    type: AuthType
    header_name: str | None = Field(default=None, alias="headerName")  # e.g., "Authorization"
    token_source: str | None = Field(default=None, alias="tokenSource")  # Where token comes from
    description: str | None = None


class QueryParam(BaseModel):
    """Describes a URL query parameter."""

    name: str
    type: str
    required: bool
    description: str | None = None


class PathParam(BaseModel):
    """Describes a URL path parameter."""

    name: str
    type: str
    description: str | None = None


class APICallSite(BaseModel):
    """Describes where an API is called from."""

    model_config = ConfigDict(populate_by_name=True)

    file_path: str = Field(alias="filePath")
    component_name: str | None = Field(default=None, alias="componentName")
    function_name: str | None = Field(default=None, alias="functionName")
    hook_name: str | None = Field(default=None, alias="hookName")
    line_number: int | None = Field(default=None, alias="lineNumber")


class ExtractedAPI(BaseModel):
    """Represents a single API endpoint extracted from code."""

    model_config = ConfigDict(populate_by_name=True)

    id: str | None = None  # Unique identifier (assigned by server)
    name: str  # Descriptive name
    endpoint: str  # URL path/pattern
    base_url: str | None = Field(default=None, alias="baseUrl")  # Base URL if known
    method: HTTPMethod
    headers: list[HeaderDefinition] | None = None
    query_params: list[QueryParam] | None = Field(default=None, alias="queryParams")
    path_params: list[PathParam] | None = Field(default=None, alias="pathParams")
    request_payload: PayloadDefinition | None = Field(default=None, alias="requestPayload")
    response_payload: PayloadDefinition | None = Field(default=None, alias="responsePayload")
    auth: AuthDefinition | None = None
    call_sites: list[APICallSite] = Field(default_factory=list, alias="callSites")
    description: str | None = None
    tags: list[str] | None = None  # Categorization
    is_deprecated: bool = Field(default=False, alias="isDeprecated")
    error_handling: str | None = Field(default=None, alias="errorHandling")


class APISummary(BaseModel):
    """Provides aggregate statistics."""

    model_config = ConfigDict(populate_by_name=True)

    total_apis: int = Field(alias="totalApis")
    by_method: dict[str, int] = Field(default_factory=dict, alias="byMethod")
    by_auth_type: dict[str, int] = Field(default_factory=dict, alias="byAuthType")
    unique_endpoints: int = Field(alias="uniqueEndpoints")


class ExtractedAPICollection(BaseModel):
    """Represents all APIs extracted from a project."""

    model_config = ConfigDict(populate_by_name=True)

    project_name: str = Field(alias="projectName")
    root_path: str = Field(alias="rootPath")
    apis: list[ExtractedAPI]
    extraction_time: str = Field(alias="extractionTime")
    files_analyzed: list[str] = Field(default_factory=list, alias="filesAnalyzed")
    http_clients: list[str] | None = Field(default=None, alias="httpClients")
    summary: APISummary


class StoredAPIList(BaseModel):
    """Represents a stored API collection with metadata."""

    model_config = ConfigDict(populate_by_name=True)

    id: str
    name: str
    collection: ExtractedAPICollection | None = None
    stored_at: str = Field(alias="storedAt")
    last_accessed: str = Field(alias="lastAccessed")

