"""Pydantic request/response models for the inference registry API.

All response models EXCLUDE actual auth_secret_ref values.
Instead they show a status string: "configured" or "not_configured".

Requirements: 3.6, 3.7
"""
from __future__ import annotations

from datetime import datetime
from typing import Any, Literal
from uuid import UUID

from pydantic import BaseModel, Field, field_validator

VALID_PROTOCOLS = ("ollama_native", "openai_chat", "specialist_http")


# ---------------------------------------------------------------------------
# Endpoint schemas
# ---------------------------------------------------------------------------


class EndpointCreate(BaseModel):
    """Request body for creating an inference endpoint."""

    name: str = Field(..., min_length=1, max_length=255)
    protocol: Literal["ollama_native", "openai_chat", "specialist_http"]
    base_url: str = Field(..., min_length=1)
    auth_secret_ref: str | None = None
    auth_scheme: str = "bearer"
    default_headers: dict[str, str] = Field(default_factory=dict)
    health_path: str | None = None
    enabled: bool = True

    @field_validator("base_url")
    @classmethod
    def validate_url(cls, v: str) -> str:
        """Validate that base_url looks like a valid URL."""
        if not v.startswith(("http://", "https://")):
            raise ValueError("base_url must start with http:// or https://")
        return v.rstrip("/")

    @field_validator("protocol")
    @classmethod
    def validate_protocol(cls, v: str) -> str:
        if v not in VALID_PROTOCOLS:
            raise ValueError(f"protocol must be one of {VALID_PROTOCOLS}")
        return v


class EndpointUpdate(BaseModel):
    """Request body for updating an inference endpoint."""

    name: str | None = None
    protocol: Literal["ollama_native", "openai_chat", "specialist_http"] | None = None
    base_url: str | None = None
    auth_secret_ref: str | None = Field(default=None)
    auth_scheme: str | None = None
    default_headers: dict[str, str] | None = None
    health_path: str | None = None
    enabled: bool | None = None

    @field_validator("base_url")
    @classmethod
    def validate_url(cls, v: str | None) -> str | None:
        if v is not None:
            if not v.startswith(("http://", "https://")):
                raise ValueError("base_url must start with http:// or https://")
            return v.rstrip("/")
        return v

    @field_validator("protocol")
    @classmethod
    def validate_protocol(cls, v: str | None) -> str | None:
        if v is not None and v not in VALID_PROTOCOLS:
            raise ValueError(f"protocol must be one of {VALID_PROTOCOLS}")
        return v


class EndpointResponse(BaseModel):
    """Response model for an inference endpoint. NEVER includes auth_secret_ref value."""

    id: UUID
    name: str
    protocol: str
    base_url: str
    auth_secret_status: str = "not_configured"  # "configured" or "not_configured"
    auth_scheme: str = "bearer"
    default_headers: dict[str, str] = Field(default_factory=dict)
    health_path: str | None = None
    enabled: bool = True
    revision: int = 1
    created_at: datetime | None = None
    updated_at: datetime | None = None
    last_probe: ProbeResponse | None = None
    capabilities: dict[str, Any] | None = None
    active_bindings: list[BindingResponse] | None = None


class EndpointListResponse(BaseModel):
    """Response model for listing endpoints."""

    id: UUID
    name: str
    protocol: str
    base_url: str
    auth_secret_status: str = "not_configured"
    enabled: bool = True
    revision: int = 1
    created_at: datetime | None = None
    updated_at: datetime | None = None


# ---------------------------------------------------------------------------
# Deployment schemas
# ---------------------------------------------------------------------------


class DeploymentCreate(BaseModel):
    """Request body for creating a model deployment."""

    endpoint_id: UUID
    served_model_name: str = Field(..., min_length=1)
    display_name: str = Field(..., min_length=1)
    capabilities: dict[str, Any] = Field(default_factory=dict)
    context_window: int | None = None
    max_output_tokens: int | None = None
    quantization: str | None = None
    runtime_metadata: dict[str, Any] = Field(default_factory=dict)
    enabled: bool = True


class DeploymentResponse(BaseModel):
    """Response model for a model deployment."""

    id: UUID
    endpoint_id: UUID
    served_model_name: str
    display_name: str
    capabilities: dict[str, Any] = Field(default_factory=dict)
    context_window: int | None = None
    max_output_tokens: int | None = None
    quantization: str | None = None
    runtime_metadata: dict[str, Any] = Field(default_factory=dict)
    enabled: bool = True
    revision: int = 1


# ---------------------------------------------------------------------------
# Binding schemas
# ---------------------------------------------------------------------------


class BindingCreate(BaseModel):
    """Request body for creating an agent stage binding."""

    agent_id: UUID
    stage: str = Field(..., min_length=1)
    model_deployment_id: UUID | None = None
    route_order: int = 0
    routing_config: dict[str, Any] = Field(default_factory=dict)
    is_active: bool = True


class BindingResponse(BaseModel):
    """Response model for an agent stage binding."""

    id: UUID
    agent_id: UUID
    stage: str
    model_deployment_id: UUID | None = None
    route_order: int = 0
    routing_config: dict[str, Any] = Field(default_factory=dict)
    is_active: bool = True
    revision: int = 1


# ---------------------------------------------------------------------------
# Probe schemas
# ---------------------------------------------------------------------------


class ProbeResponse(BaseModel):
    """Response model for probe results."""

    endpoint_id: UUID
    timestamp: datetime | None = None
    software_version: str | None = None
    probe_duration_ms: int = 0
    health_success: bool = False
    health_detail: str = ""
    model_listing_success: bool | None = None
    json_schema_success: bool | None = None
    usage_success: bool | None = None
    seed_success: bool | None = None
    output_token_field_success: bool | None = None


# ---------------------------------------------------------------------------
# Egress confirmation schema
# ---------------------------------------------------------------------------


class EgressConfirmation(BaseModel):
    """Request body for confirming external endpoint egress enablement.

    Requires explicit confirmed=true flag.
    """

    confirmed: bool = Field(
        ...,
        description="Must be explicitly set to true to confirm external egress enablement",
    )

    @field_validator("confirmed")
    @classmethod
    def must_be_true(cls, v: bool) -> bool:
        if not v:
            raise ValueError("confirmed must be true to enable external egress")
        return v


# ---------------------------------------------------------------------------
# Structured output test schemas
# ---------------------------------------------------------------------------


class StructuredOutputTestRequest(BaseModel):
    """Request body for testing structured output on an endpoint."""

    json_schema: dict[str, Any] = Field(
        default_factory=lambda: {
            "type": "object",
            "properties": {"status": {"type": "string"}},
            "required": ["status"],
        }
    )
    prompt: str = 'Respond with JSON: {"status": "ok"}'


class StructuredOutputTestResponse(BaseModel):
    """Response for structured output test."""

    success: bool
    structured_mode: str = ""
    content: str = ""
    parsed: dict[str, Any] | None = None
    schema_valid: bool = False
    latency_ms: int = 0
    error: str | None = None
