from typing import Annotated
from pydantic import BaseModel, ConfigDict, Field, field_validator, BeforeValidator
from decimal import Decimal

StrId = Annotated[str, BeforeValidator(str)]


class CalculatordefaultsBase(BaseModel):
    default_principal: Decimal = Field(..., max_digits=15, decimal_places=2, ge=0)
    default_interest_rate: Decimal = Field(..., max_digits=5, decimal_places=2, ge=0)
    default_term_months: int = Field(..., ge=1)
    min_principal: Decimal = Field(..., max_digits=15, decimal_places=2, ge=0)
    max_principal: Decimal = Field(..., max_digits=15, decimal_places=2, ge=0)
    min_interest_rate: Decimal = Field(..., max_digits=5, decimal_places=2, ge=0)
    max_interest_rate: Decimal = Field(..., max_digits=5, decimal_places=2, ge=0)
    min_term_months: int = Field(..., ge=1)
    max_term_months: int = Field(..., ge=1)

    @field_validator("default_principal", "min_principal", "max_principal")
    @classmethod
    def validate_principal_positive(cls, v):
        if v is not None and v <= 0:
            raise ValueError("Principal amount must be positive")
        return v

    @field_validator("default_interest_rate", "min_interest_rate", "max_interest_rate")
    @classmethod
    def validate_interest_rate_non_negative(cls, v):
        if v is not None and v < 0:
            raise ValueError("Interest rate cannot be negative")
        return v

    @field_validator("default_term_months", "min_term_months", "max_term_months")
    @classmethod
    def validate_term_positive(cls, v):
        if v is not None and v <= 0:
            raise ValueError("Term must be a positive integer")
        return v


class CalculatordefaultsCreate(CalculatordefaultsBase):
    pass


class CalculatordefaultsUpdate(BaseModel):
    default_principal: Decimal | None = Field(None, max_digits=15, decimal_places=2, ge=0)
    default_interest_rate: Decimal | None = Field(None, max_digits=5, decimal_places=2, ge=0)
    default_term_months: int | None = Field(None, ge=1)
    min_principal: Decimal | None = Field(None, max_digits=15, decimal_places=2, ge=0)
    max_principal: Decimal | None = Field(None, max_digits=15, decimal_places=2, ge=0)
    min_interest_rate: Decimal | None = Field(None, max_digits=5, decimal_places=2, ge=0)
    max_interest_rate: Decimal | None = Field(None, max_digits=5, decimal_places=2, ge=0)
    min_term_months: int | None = Field(None, ge=1)
    max_term_months: int | None = Field(None, ge=1)

    @field_validator("default_principal", "min_principal", "max_principal")
    @classmethod
    def validate_principal_positive(cls, v):
        if v is not None and v <= 0:
            raise ValueError("Principal amount must be positive")
        return v

    @field_validator("default_interest_rate", "min_interest_rate", "max_interest_rate")
    @classmethod
    def validate_interest_rate_non_negative(cls, v):
        if v is not None and v < 0:
            raise ValueError("Interest rate cannot be negative")
        return v

    @field_validator("default_term_months", "min_term_months", "max_term_months")
    @classmethod
    def validate_term_positive(cls, v):
        if v is not None and v <= 0:
            raise ValueError("Term must be a positive integer")
        return v


class CalculatordefaultsResponse(CalculatordefaultsBase):
    id: StrId
    created_at: str
    updated_at: str

    model_config = ConfigDict(from_attributes=True)