"""Phase 7.5 Referral Engine validators — program status, attribution rules, transitions."""
from __future__ import annotations

from uuid import UUID

from shared.exceptions import AppError

from app.models.types import (
    ReferralAttributionStatus,
    ReferralCodeStatus,
    ReferralProgramStatus,
)


def validate_referral_program_status(
    status: ReferralProgramStatus | str,
) -> ReferralProgramStatus:
    if isinstance(status, ReferralProgramStatus):
        return status
    try:
        return ReferralProgramStatus(status)
    except ValueError as exc:
        raise AppError(
            "وضعیت برنامه معرفی نامعتبر است",
            status_code=422,
            error_code="invalid_referral_program_status",
        ) from exc


def ensure_referral_program_active(status: ReferralProgramStatus) -> None:
    if status != ReferralProgramStatus.ACTIVE:
        raise AppError(
            "برنامه معرفی فعال نیست",
            status_code=409,
            error_code="referral_program_not_active",
        )


def ensure_code_active(status: ReferralCodeStatus) -> None:
    if status != ReferralCodeStatus.ACTIVE:
        raise AppError(
            "کد معرفی فعال نیست",
            status_code=409,
            error_code="referral_code_not_active",
        )


def ensure_not_self_referral(referrer_member_id: UUID, referee_member_id: UUID) -> None:
    if referrer_member_id == referee_member_id:
        raise AppError(
            "معرفی خود فرد مجاز نیست",
            status_code=422,
            error_code="referral_self_referral_forbidden",
        )


def ensure_max_referrals_not_exceeded(
    current_count: int, max_referrals: int | None
) -> None:
    if max_referrals is not None and current_count >= max_referrals:
        raise AppError(
            "سقف تعداد معرفی‌های این عضو تکمیل شده است",
            status_code=409,
            error_code="referral_max_referrals_exceeded",
        )


def ensure_attribution_pending(status: ReferralAttributionStatus) -> None:
    if status != ReferralAttributionStatus.PENDING:
        raise AppError(
            "وضعیت معرفی برای تبدیل مناسب نیست",
            status_code=409,
            error_code="referral_not_pending",
        )


def ensure_attribution_converted(status: ReferralAttributionStatus) -> None:
    if status != ReferralAttributionStatus.CONVERTED:
        raise AppError(
            "معرفی باید ابتدا تبدیل شده باشد",
            status_code=409,
            error_code="referral_not_converted",
        )


def ensure_attribution_cancellable(status: ReferralAttributionStatus) -> None:
    if status in (
        ReferralAttributionStatus.REWARDED,
        ReferralAttributionStatus.CANCELLED,
    ):
        raise AppError(
            "این معرفی قابل لغو نیست",
            status_code=409,
            error_code="referral_not_cancellable",
        )
