"""Proxy domain schemas — request, response, and patch.

Uses repo_core base classes:
    - ``BaseRequestSchema`` — inbound (extra="forbid")
    - ``BaseResponseSchema`` — outbound (from_attributes=True)
    - ``BasePatchSchema`` — partial updates
"""

from __future__ import annotations

import uuid
from datetime import datetime
from typing import Any

from pydantic import BaseModel, Field, field_validator, model_validator

from repo_core.base.schemas import BaseRequestSchema, BaseResponseSchema, BasePatchSchema
from repo_core.domains.proxy.model import AccountType, LeaseMode


# -- Create ---------------------------------------------------------------

class CreateProxyRequest(BaseRequestSchema):
    """Payload for registering a new proxy server."""
    id: str = Field(..., min_length=1)
    username: str = Field(..., min_length=1)
    password: str = Field(..., min_length=1)
    proxy_address: str = Field(..., min_length=1)
    port: int = Field(..., ge=1, le=65535)
    country_code: str | None = None
    city_name: str | None = None
    asn_name: str | None = None
    asn_number: int | None = None
    high_country_confidence: bool = True


# -- Response -------------------------------------------------------------

class ProxyResponse(BaseResponseSchema):
    """Proxy server API response."""
    id: str
    username: str
    password: str
    proxy_address: str
    port: int
    valid: bool = True
    last_verification: datetime | None = None
    country_code: str | None = None
    city_name: str | None = None
    asn_name: str | None = None
    asn_number: int | None = None
    high_country_confidence: bool = True
    average_delay: float | None = None
    average_speed: float | None = None
    last_time_tested: datetime | None = None
    created_at: datetime | None = None
    updated_at: datetime | None = None


class ProxyListResponse(BaseModel):
    items: list[ProxyResponse]
    total: int
    limit: int
    offset: int


# -- Patch ----------------------------------------------------------------

class PatchProxyRequest(BasePatchSchema):
    """Partial update payload for a proxy server.

    Only explicitly-set fields are included in the patch dict::

        patch = PatchProxyRequest(valid=False, average_delay=120.5)
        update_fields = patch.to_patch_dict()
    """
    valid: bool | None = None
    last_verification: datetime | None = None
    country_code: str | None = None
    city_name: str | None = None
    asn_name: str | None = None
    asn_number: int | None = None
    high_country_confidence: bool | None = None
    average_delay: float | None = None
    average_speed: float | None = None
    last_time_tested: datetime | None = None


# =========================================================================
# Proxy Lease
# =========================================================================


class CreateLeaseRequest(BaseRequestSchema):
    """Lease a proxy to a platform account.

    ``account_type`` discriminates which table ``account_id`` references
    (``x_accounts``, ``telegram_accounts``, ``instagram_accounts``).
    """

    proxy_id: str = Field(..., min_length=1)
    account_type: AccountType
    account_id: uuid.UUID
    lease_mode: LeaseMode
    lease_duration_seconds: int | None = None

    @model_validator(mode="after")
    def _duration_required_for_timed(self) -> "CreateLeaseRequest":
        if self.lease_mode == "timed" and (self.lease_duration_seconds is None or self.lease_duration_seconds <= 0):
            raise ValueError("lease_duration_seconds is required and must be > 0 for timed leases")
        return self


class LeaseResponse(BaseResponseSchema):
    """Proxy lease API response."""
    id: uuid.UUID
    proxy_id: str
    account_type: AccountType
    account_id: uuid.UUID
    lease_mode: LeaseMode
    lease_duration_seconds: int | None = None
    assigned_at: datetime | None = None
    expires_at: datetime | None = None
    reclaimed_at: datetime | None = None
    is_active: bool = True
    created_at: datetime | None = None
    updated_at: datetime | None = None


class LeaseListResponse(BaseModel):
    items: list[LeaseResponse]
    total: int
    limit: int
    offset: int


class PatchLeaseRequest(BasePatchSchema):
    """Partial update for a lease (e.g., reclaim a proxy)."""
    is_active: bool | None = None
    reclaimed_at: datetime | None = None
    lease_mode: LeaseMode | None = None
    lease_duration_seconds: int | None = None
