"""Type definitions for ingress-edge SDK.

All types use Pydantic v2 for runtime validation (Python equivalent of Zod).
Field names use snake_case to match backend conventions.
"""

from datetime import datetime
from typing import Any

from pydantic import BaseModel, ConfigDict, Field


class IngressDataPoint(BaseModel):
    """Single data point sent to ingress core.

    IMPORTANT: Field names use snake_case to match backend conventions.
    """

    model_config = ConfigDict(strict=True)

    channel_id: str = Field(..., min_length=1, description="Channel ID (required)")
    timestamp: datetime = Field(..., description="ISO 8601 datetime")
    data: dict[str, Any] = Field(..., description="Arbitrary JSON data")


class IngressBatchRequest(BaseModel):
    """Batch request containing multiple data points.

    Max 1000 points per batch to ensure reasonable request sizes.
    """

    model_config = ConfigDict(strict=True)

    points: list[IngressDataPoint] = Field(
        ..., min_length=1, max_length=1000, description="Data points to ingest"
    )


class IngestError(BaseModel):
    """Error details for rejected data points in a batch."""

    model_config = ConfigDict(strict=True)

    index: int = Field(..., ge=0, description="Index of the rejected point")
    reason: str = Field(..., description="Reason for rejection")


class IngressResponse(BaseModel):
    """Response from ingress core after processing a batch."""

    model_config = ConfigDict(strict=True)

    accepted: int = Field(..., ge=0, description="Number of points accepted")
    rejected: int = Field(..., ge=0, description="Number of points rejected")
    errors: list[IngestError] | None = Field(
        None, description="Details of rejected points"
    )


class IngressClientConfig(BaseModel):
    """Client configuration options."""

    model_config = ConfigDict(strict=True)

    base_url: str = Field(..., description="Base URL of the ingress core")
    api_key: str = Field(..., description="API key for authentication")
    batch_size: int = Field(
        100, ge=1, le=1000, description="Points to batch before sending"
    )
    batch_timeout: float = Field(
        5.0, gt=0, description="Seconds to wait before flushing batch"
    )
    max_retries: int = Field(
        5, ge=0, description="Maximum retry attempts for failed requests"
    )
    offline_buffer_size: int = Field(
        10000, ge=0, description="Maximum points to buffer offline"
    )


class BufferStats(BaseModel):
    """Offline buffer statistics."""

    model_config = ConfigDict(strict=True)

    size: int = Field(..., ge=0, description="Current points in buffer")
    max_size: int = Field(..., ge=0, description="Maximum buffer capacity")
    is_at_capacity: bool = Field(..., description="Whether buffer is full")
