"""Membership Catalog validators — Phase 9.1."""
from __future__ import annotations

from decimal import Decimal

from app.models.types import BillingPeriod, PricingModelKind, RuleKind
from shared.exceptions import AppError


def validate_age_range(min_age: int | None, max_age: int | None) -> tuple[int | None, int | None]:
    if min_age is not None and min_age < 0:
        raise AppError("حداقل سن نامعتبر است", status_code=422, error_code="invalid_min_age")
    if max_age is not None and max_age < 0:
        raise AppError("حداکثر سن نامعتبر است", status_code=422, error_code="invalid_max_age")
    if min_age is not None and max_age is not None and min_age > max_age:
        raise AppError(
            "حداقل سن نمی‌تواند از حداکثر سن بیشتر باشد",
            status_code=422,
            error_code="invalid_age_range",
        )
    return min_age, max_age


def validate_pricing_kind(value: PricingModelKind | str) -> PricingModelKind:
    try:
        return value if isinstance(value, PricingModelKind) else PricingModelKind(value)
    except ValueError as exc:
        raise AppError("مدل قیمت‌گذاری نامعتبر است", status_code=422, error_code="invalid_pricing_kind") from exc


def validate_billing_period(value: BillingPeriod | str) -> BillingPeriod:
    try:
        return value if isinstance(value, BillingPeriod) else BillingPeriod(value)
    except ValueError as exc:
        raise AppError("دوره صورتحساب نامعتبر است", status_code=422, error_code="invalid_billing_period") from exc


def validate_rule_kind(value: RuleKind | str) -> RuleKind:
    try:
        return value if isinstance(value, RuleKind) else RuleKind(value)
    except ValueError as exc:
        raise AppError("نوع قانون نامعتبر است", status_code=422, error_code="invalid_rule_kind") from exc


def validate_money_amount(amount: Decimal | None, *, field: str = "amount") -> Decimal | None:
    if amount is None:
        return None
    if amount < 0:
        raise AppError(f"{field} نمی‌تواند منفی باشد", status_code=422, error_code="invalid_amount")
    return amount
