"""Wallet Engine validators — Phase 7.6."""
from __future__ import annotations

from shared.exceptions import AppError

from app.models.types import WalletAccountStatus, WalletLedgerEntryType


def validate_wallet_account_status(
    status: WalletAccountStatus | str,
) -> WalletAccountStatus:
    if isinstance(status, WalletAccountStatus):
        return status
    try:
        return WalletAccountStatus(status)
    except ValueError as exc:
        raise AppError(
            "وضعیت کیف پول نامعتبر است",
            status_code=422,
            error_code="invalid_wallet_account_status",
        ) from exc


def ensure_wallet_open(status: WalletAccountStatus) -> None:
    if status == WalletAccountStatus.CLOSED:
        raise AppError(
            "کیف پول بسته است",
            status_code=409,
            error_code="wallet_account_closed",
        )
    if status == WalletAccountStatus.FROZEN:
        raise AppError(
            "کیف پول مسدود است",
            status_code=409,
            error_code="wallet_account_frozen",
        )


def validate_positive_amount(amount: int, *, field: str = "amount") -> int:
    if amount is None or amount <= 0:
        raise AppError(
            f"{field} باید بزرگ‌تر از صفر باشد",
            status_code=422,
            error_code="invalid_wallet_amount",
            details={"field": field},
        )
    return amount


def validate_adjust_amount(amount: int) -> int:
    if amount == 0:
        raise AppError(
            "مقدار تعدیل نمی‌تواند صفر باشد",
            status_code=422,
            error_code="invalid_wallet_adjust_amount",
        )
    return amount


def signed_amount(entry_type: WalletLedgerEntryType, amount: int) -> int:
    if entry_type in {WalletLedgerEntryType.CREDIT, WalletLedgerEntryType.TRANSFER_IN}:
        return abs(amount)
    if entry_type in {WalletLedgerEntryType.DEBIT, WalletLedgerEntryType.TRANSFER_OUT}:
        return -abs(amount)
    # ADJUST: caller supplies signed amount
    return amount


def ensure_sufficient_funds(balance: int, new_balance: int, *, requested: int) -> None:
    if new_balance < 0:
        raise AppError(
            "موجودی کیف پول کافی نیست",
            status_code=409,
            error_code="wallet_insufficient_funds",
            details={"balance": balance, "requested": requested},
        )


def ensure_same_currency(source_currency: str, target_currency: str) -> None:
    if source_currency != target_currency:
        raise AppError(
            "انتقال بین ارزهای متفاوت مجاز نیست",
            status_code=422,
            error_code="wallet_currency_mismatch",
            details={"source": source_currency, "target": target_currency},
        )


def ensure_not_same_account(source_id, target_id) -> None:
    if source_id == target_id:
        raise AppError(
            "انتقال به همان کیف پول مجاز نیست",
            status_code=422,
            error_code="wallet_transfer_same_account",
        )
