"""
Request/Response models for metadata store endpoints.
"""

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, ConfigDict, Field, field_validator

from pycharter.shared.name_validator import validate_name


class SchemaStoreRequest(BaseModel):
    """Request model for storing a schema."""

    schema_name: str = Field(..., description="Schema name/identifier")
    schema: dict[str, Any] = Field(
        ..., description="JSON Schema definition", alias="schema"
    )
    version: str = Field(..., description="Schema version")

    @field_validator("schema_name")
    @classmethod
    def validate_schema_name(cls, v: str) -> str:
        """Validate schema name follows naming convention."""
        return validate_name(v, field_name="schema_name")

    @field_validator("schema")
    @classmethod
    def validate_schema_title(cls, v: dict[str, Any], info) -> dict[str, Any]:
        """Validate schema title if present in schema."""
        if isinstance(v, dict) and "title" in v and v["title"]:
            v["title"] = validate_name(str(v["title"]), field_name="schema.title")
        return v

    model_config = ConfigDict(
        populate_by_name=True,
        json_schema_extra={
            "example": {
                "schema_name": "user_schema",
                "schema": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                        "age": {"type": "integer"},
                    },
                },
                "version": "1.0.0",
            }
        },
    )


class SchemaStoreResponse(BaseModel):
    """Response model for stored schema."""

    schema_id: str = Field(..., description="Schema identifier")
    schema_name: str = Field(..., description="Schema name")
    version: str = Field(..., description="Schema version")

    class Config:
        json_schema_extra = {
            "example": {
                "schema_id": "schema_1",
                "schema_name": "user_schema",
                "version": "1.0.0",
            }
        }


class SchemaGetRequest(BaseModel):
    """Request model for retrieving a schema."""

    schema_id: str = Field(..., description="Schema identifier")
    version: str | None = Field(None, description="Schema version (default: latest)")

    class Config:
        json_schema_extra = {"example": {"schema_id": "schema_1", "version": "1.0.0"}}


class SchemaGetResponse(BaseModel):
    """Response model for retrieved schema."""

    schema: dict[str, Any] = Field(
        ..., description="JSON Schema definition", alias="schema"
    )
    version: str | None = Field(None, description="Schema version")

    model_config = ConfigDict(
        populate_by_name=True,
        json_schema_extra={
            "example": {
                "schema": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                        "age": {"type": "integer"},
                    },
                },
                "version": "1.0.0",
            }
        },
    )


class MetadataStoreRequest(BaseModel):
    """Request model for storing metadata (contract-centric)."""

    contract_name: str = Field(..., description="Data contract name")
    contract_version: str = Field(..., description="Data contract version")
    metadata: dict[str, Any] = Field(..., description="Metadata dictionary")

    @field_validator("metadata")
    @classmethod
    def validate_metadata_title(cls, v: dict[str, Any]) -> dict[str, Any]:
        if isinstance(v, dict) and "title" in v and v["title"]:
            v["title"] = validate_name(str(v["title"]), field_name="metadata.title")
        return v

    class Config:
        json_schema_extra = {
            "example": {
                "contract_name": "user_schema",
                "contract_version": "1.0.0",
                "metadata": {
                    "title": "User Schema Metadata",
                    "description": "Metadata for user schema",
                    "business_owners": ["owner@example.com"],
                },
            }
        }


class MetadataStoreResponse(BaseModel):
    """Response model for stored metadata."""

    metadata_id: str = Field(..., description="Metadata record identifier")
    contract_name: str = Field(..., description="Data contract name")
    contract_version: str = Field(..., description="Data contract version")

    class Config:
        json_schema_extra = {
            "example": {
                "metadata_id": "metadata_1",
                "contract_name": "user_schema",
                "contract_version": "1.0.0",
            }
        }


class MetadataGetRequest(BaseModel):
    """Request model for retrieving metadata."""

    schema_id: str = Field(..., description="Schema identifier")
    version: str | None = Field(
        None, description="Version string (default: uses latest version)"
    )

    class Config:
        json_schema_extra = {"example": {"schema_id": "schema_1", "version": "1.0.0"}}


class MetadataGetResponse(BaseModel):
    """Response model for retrieved metadata."""

    metadata: dict[str, Any] = Field(..., description="Metadata dictionary")

    class Config:
        json_schema_extra = {
            "example": {
                "metadata": {
                    "title": "User Schema Metadata",
                    "description": "Metadata for user schema",
                    "business_owners": ["owner@example.com"],
                }
            }
        }


class CoercionRulesStoreRequest(BaseModel):
    """Request model for storing coercion rules (contract-centric)."""

    contract_name: str = Field(..., description="Data contract name")
    contract_version: str = Field(..., description="Data contract version")
    coercion_rules: dict[str, Any] = Field(..., description="Coercion rules dictionary")

    class Config:
        json_schema_extra = {
            "example": {
                "contract_name": "user_schema",
                "contract_version": "1.0.0",
                "coercion_rules": {
                    "age": "coerce_to_integer",
                    "email": "coerce_to_lowercase",
                },
            }
        }


class ValidationRulesStoreRequest(BaseModel):
    """Request model for storing validation rules (contract-centric)."""

    contract_name: str = Field(..., description="Data contract name")
    contract_version: str = Field(..., description="Data contract version")
    validation_rules: dict[str, Any] = Field(
        ..., description="Validation rules dictionary"
    )

    class Config:
        json_schema_extra = {
            "example": {
                "contract_name": "user_schema",
                "contract_version": "1.0.0",
                "validation_rules": {
                    "age": {"is_positive": {}, "is_in_range": {"min": 0, "max": 150}}
                },
            }
        }


class RulesStoreResponse(BaseModel):
    """Response model for stored rules (contract-centric)."""

    rule_id: str = Field(..., description="Rule identifier")
    contract_name: str = Field(..., description="Data contract name")
    contract_version: str = Field(..., description="Data contract version")

    class Config:
        json_schema_extra = {
            "example": {
                "rule_id": "coercion_1",
                "contract_name": "user_schema",
                "contract_version": "1.0.0",
            }
        }


class SchemaListItem(BaseModel):
    """Schema list item model."""

    id: str = Field(..., description="Schema identifier")
    name: str | None = Field(None, description="Schema name")
    title: str | None = Field(None, description="Schema title")
    version: str | None = Field(None, description="Schema version")


class SchemaListResponse(BaseModel):
    """Response model for listing schemas."""

    schemas: list[SchemaListItem] = Field(..., description="List of schemas")
    count: int = Field(..., description="Total number of schemas")

    class Config:
        json_schema_extra = {
            "example": {
                "schemas": [
                    {
                        "id": "schema_1",
                        "name": "user_schema",
                        "title": "User Schema",
                        "version": "1.0.0",
                    }
                ],
                "count": 1,
            }
        }


class RulesGetResponse(BaseModel):
    """Response model for retrieving rules (contract-centric)."""

    rules: dict[str, Any] = Field(..., description="Rules dictionary")
    contract_name: str = Field(..., description="Data contract name")
    contract_version: str = Field(..., description="Data contract version")

    class Config:
        json_schema_extra = {
            "example": {
                "rules": {"age": "coerce_to_integer", "email": "coerce_to_lowercase"},
                "contract_name": "user_schema",
                "contract_version": "1.0.0",
            }
        }
