# states/order.py

from __future__ import annotations

from typing import Final

from aiogram.fsm.state import State, StatesGroup


# ============================================================
# User Order FSM
# ============================================================

class OrderStates(StatesGroup):
    """
    Stateهای موقتی گفت‌وگوی سفارش کاربر.

    نکته بسیار مهم:
        FSM منبع حقیقت سفارش نیست.

    وضعیت واقعی سفارش بعد از ثبت درخواست باید در:
        orders.status

    ذخیره شود تا Restart ربات باعث گم شدن وضعیت سفارش نشود.

    جریان اصلی Owner Approval:

        selecting_package
            ↓
        waiting_for_amount / waiting_for_duration
            ↓
        waiting_for_target_account
            ↓
        reviewing_order
            ↓
        waiting_for_request_confirmation
            ↓
        سفارش در DB:
            pending_owner_approval

    بعد از ثبت در DB معمولاً FSM کاربر clear می‌شود.
    """

    # --------------------------------------------------------
    # Product
    # --------------------------------------------------------

    selecting_package = State()

    # --------------------------------------------------------
    # Amount / Duration
    # --------------------------------------------------------

    waiting_for_amount = State()

    # Legacy compatibility
    waiting_for_custom_amount = State()

    waiting_for_duration = State()

    # --------------------------------------------------------
    # Target
    # --------------------------------------------------------

    waiting_for_target_account = State()

    # Legacy aliases used by older handlers
    waiting_for_target = State()
    waiting_for_username = State()
    waiting_for_recipient = State()

    # --------------------------------------------------------
    # Review / User Confirmation
    # --------------------------------------------------------

    reviewing_order = State()

    waiting_for_request_confirmation = State()

    # Legacy name:
    # در معماری جدید این State دیگر به معنی پرداخت نیست؛
    # فقط برای شکسته نشدن Handlerهای قبلی نگه داشته شده.
    waiting_for_payment_confirmation = State()

    # --------------------------------------------------------
    # Owner Approval
    # --------------------------------------------------------

    waiting_for_owner_approval = State()

    owner_rejected = State()

    validating_final_order = State()

    price_changed = State()

    insufficient_balance = State()

    # --------------------------------------------------------
    # Payment
    # --------------------------------------------------------

    processing_payment = State()

    # Crypto / external payments
    waiting_for_payment = State()

    verifying_payment = State()

    # --------------------------------------------------------
    # Provider
    # --------------------------------------------------------

    processing_provider = State()

    # Legacy generic name
    processing_order = State()

    waiting_for_provider = State()

    provider_status_unknown = State()

    # فقط برای Providerهایی که endpoint رسمی استعلام دارند.
    # برای MarketApp فعلی نباید بدون endpoint رسمی از آن استفاده شود.
    checking_order_status = State()

    # --------------------------------------------------------
    # Final UI States
    # --------------------------------------------------------

    order_completed = State()

    order_failed = State()

    order_cancelled = State()

    # --------------------------------------------------------
    # Support
    # --------------------------------------------------------

    waiting_for_support = State()


# ============================================================
# Payment FSM
# ============================================================

class PaymentStates(StatesGroup):
    """
    Stateهای مستقل پرداخت.

    برای Wallet داخلی Premium/Stars معمولاً این Stateها لازم
    نیستند؛ بیشتر برای TON / TRX / USDT و پرداخت خارجی‌اند.
    """

    selecting_method = State()

    waiting_for_transaction_hash = State()

    verifying_transaction = State()

    payment_confirmed = State()

    payment_failed = State()

    payment_expired = State()


# ============================================================
# Admin / Owner Order FSM
# ============================================================

class AdminOrderStates(StatesGroup):
    """
    Stateهای چندمرحله‌ای مدیریت سفارش.

    تایید/رد ساده Owner با callback و وضعیت دیتابیس انجام می‌شود
    و الزاماً نیازی به FSM ندارد.
    """

    searching_order = State()

    viewing_order = State()

    reviewing_owner_request = State()

    confirming_approval = State()

    entering_reject_reason = State()

    changing_order_status = State()

    entering_admin_note = State()

    resolving_provider_unknown = State()

    confirming_manual_refund = State()

    confirming_manual_completion = State()


# ============================================================
# Persistent DB Order Statuses
# ============================================================

class OrderStatus:
    """
    وضعیت‌های دائمی orders.status.

    این کلاس StatesGroup نیست.

    مسیر اصلی:

        pending_owner_approval
            ↓
        owner_processing
            ↓
        provider_processing
            ↓
        completed

    مسیرهای جایگزین:

        rejected_by_owner
        price_changed
        insufficient_balance
        failed_refunded
        failed_refund_required
        provider_status_unknown
    """

    # --------------------------------------------------------
    # Owner Approval
    # --------------------------------------------------------

    PENDING_OWNER_APPROVAL: Final[str] = (
        "pending_owner_approval"
    )

    OWNER_PROCESSING: Final[str] = (
        "owner_processing"
    )

    REJECTED_BY_OWNER: Final[str] = (
        "rejected_by_owner"
    )

    CANCELLED_BY_USER: Final[str] = (
        "cancelled_by_user"
    )

    # --------------------------------------------------------
    # Validation
    # --------------------------------------------------------

    PRICE_CHANGED: Final[str] = (
        "price_changed"
    )

    INSUFFICIENT_BALANCE: Final[str] = (
        "insufficient_balance"
    )

    # --------------------------------------------------------
    # Provider
    # --------------------------------------------------------

    PROVIDER_PROCESSING: Final[str] = (
        "provider_processing"
    )

    PROVIDER_STATUS_UNKNOWN: Final[str] = (
        "provider_status_unknown"
    )

    # --------------------------------------------------------
    # Final
    # --------------------------------------------------------

    COMPLETED: Final[str] = (
        "completed"
    )

    FAILED_REFUNDED: Final[str] = (
        "failed_refunded"
    )

    FAILED_REFUND_REQUIRED: Final[str] = (
        "failed_refund_required"
    )

    CANCELLED: Final[str] = (
        "cancelled"
    )

    REFUNDED: Final[str] = (
        "refunded"
    )

    # --------------------------------------------------------
    # Legacy DB statuses
    # --------------------------------------------------------

    PENDING: Final[str] = (
        "pending"
    )

    PROCESSING: Final[str] = (
        "processing"
    )

    PAID: Final[str] = (
        "paid"
    )

    FAILED: Final[str] = (
        "failed"
    )

    CREATED: Final[str] = (
        "created"
    )


# ============================================================
# Valid DB Statuses
# ============================================================

ORDER_DB_STATUSES: Final[
    frozenset[str]
] = frozenset(
    {
        OrderStatus.PENDING_OWNER_APPROVAL,
        OrderStatus.OWNER_PROCESSING,
        OrderStatus.REJECTED_BY_OWNER,
        OrderStatus.CANCELLED_BY_USER,

        OrderStatus.PRICE_CHANGED,
        OrderStatus.INSUFFICIENT_BALANCE,

        OrderStatus.PROVIDER_PROCESSING,
        OrderStatus.PROVIDER_STATUS_UNKNOWN,

        OrderStatus.COMPLETED,
        OrderStatus.FAILED_REFUNDED,
        OrderStatus.FAILED_REFUND_REQUIRED,
        OrderStatus.CANCELLED,
        OrderStatus.REFUNDED,

        # Legacy
        OrderStatus.PENDING,
        OrderStatus.PROCESSING,
        OrderStatus.PAID,
        OrderStatus.FAILED,
        OrderStatus.CREATED,
    }
)


# ============================================================
# Status Groups
# ============================================================

OWNER_PENDING_STATUSES: Final[
    frozenset[str]
] = frozenset(
    {
        OrderStatus.PENDING_OWNER_APPROVAL,
    }
)


PROCESSING_STATUSES: Final[
    frozenset[str]
] = frozenset(
    {
        OrderStatus.OWNER_PROCESSING,
        OrderStatus.PROVIDER_PROCESSING,
    }
)


SUCCESS_STATUSES: Final[
    frozenset[str]
] = frozenset(
    {
        OrderStatus.COMPLETED,
    }
)


FAILURE_STATUSES: Final[
    frozenset[str]
] = frozenset(
    {
        OrderStatus.REJECTED_BY_OWNER,
        OrderStatus.CANCELLED_BY_USER,
        OrderStatus.PRICE_CHANGED,
        OrderStatus.INSUFFICIENT_BALANCE,
        OrderStatus.FAILED_REFUNDED,
        OrderStatus.FAILED_REFUND_REQUIRED,
        OrderStatus.CANCELLED,
    }
)


MANUAL_REVIEW_STATUSES: Final[
    frozenset[str]
] = frozenset(
    {
        OrderStatus.PROVIDER_STATUS_UNKNOWN,
        OrderStatus.FAILED_REFUND_REQUIRED,
    }
)


TERMINAL_STATUSES: Final[
    frozenset[str]
] = frozenset(
    {
        OrderStatus.REJECTED_BY_OWNER,
        OrderStatus.CANCELLED_BY_USER,
        OrderStatus.PRICE_CHANGED,
        OrderStatus.INSUFFICIENT_BALANCE,
        OrderStatus.COMPLETED,
        OrderStatus.FAILED_REFUNDED,
        OrderStatus.CANCELLED,
        OrderStatus.REFUNDED,

        # Legacy terminal statuses
        OrderStatus.FAILED,
    }
)


# ============================================================
# Human-readable DB Status Names
# ============================================================

ORDER_STATUS_NAMES: Final[
    dict[str, str]
] = {
    OrderStatus.PENDING_OWNER_APPROVAL:
        "در انتظار تایید مالک",

    OrderStatus.OWNER_PROCESSING:
        "در حال بررسی توسط مالک",

    OrderStatus.REJECTED_BY_OWNER:
        "رد شده توسط مالک",

    OrderStatus.CANCELLED_BY_USER:
        "لغو شده توسط کاربر",

    OrderStatus.PRICE_CHANGED:
        "قیمت تغییر کرده",

    OrderStatus.INSUFFICIENT_BALANCE:
        "موجودی ناکافی",

    OrderStatus.PROVIDER_PROCESSING:
        "در حال تحویل سفارش",

    OrderStatus.PROVIDER_STATUS_UNKNOWN:
        "نیازمند بررسی دستی سفارش",

    OrderStatus.COMPLETED:
        "تکمیل شده",

    OrderStatus.FAILED_REFUNDED:
        "ناموفق - مبلغ برگشت داده شد",

    OrderStatus.FAILED_REFUND_REQUIRED:
        "ناموفق - نیازمند بررسی مالی",

    OrderStatus.CANCELLED:
        "لغو شده",

    OrderStatus.REFUNDED:
        "مبلغ برگشت داده شد",

    # Legacy
    OrderStatus.PENDING:
        "در انتظار",

    OrderStatus.PROCESSING:
        "در حال پردازش",

    OrderStatus.PAID:
        "پرداخت شده",

    OrderStatus.FAILED:
        "ناموفق",

    OrderStatus.CREATED:
        "ایجاد شده",
}


# ============================================================
# Human-readable User FSM Names
# ============================================================

ORDER_STATE_NAMES: Final[
    dict[str, str]
] = {
    "selecting_package":
        "انتخاب پکیج",

    "waiting_for_amount":
        "دریافت مقدار",

    "waiting_for_custom_amount":
        "دریافت مقدار دلخواه",

    "waiting_for_duration":
        "دریافت مدت",

    "waiting_for_target_account":
        "دریافت مقصد",

    "waiting_for_target":
        "دریافت مقصد",

    "waiting_for_username":
        "دریافت یوزرنیم",

    "waiting_for_recipient":
        "دریافت گیرنده",

    "reviewing_order":
        "بازبینی سفارش",

    "waiting_for_request_confirmation":
        "انتظار تایید ثبت درخواست",

    "waiting_for_payment_confirmation":
        "انتظار تایید ثبت درخواست",

    "waiting_for_owner_approval":
        "در انتظار تایید مالک",

    "owner_rejected":
        "رد شده توسط مالک",

    "validating_final_order":
        "بررسی نهایی سفارش",

    "price_changed":
        "قیمت تغییر کرده",

    "insufficient_balance":
        "موجودی ناکافی",

    "processing_payment":
        "پردازش مالی",

    "waiting_for_payment":
        "انتظار پرداخت",

    "verifying_payment":
        "بررسی پرداخت",

    "processing_provider":
        "پردازش سرویس‌دهنده",

    "processing_order":
        "پردازش سفارش",

    "waiting_for_provider":
        "انتظار پاسخ سرویس‌دهنده",

    "provider_status_unknown":
        "وضعیت سرویس‌دهنده نامشخص",

    "checking_order_status":
        "بررسی وضعیت سفارش",

    "order_completed":
        "سفارش تکمیل شد",

    "order_failed":
        "سفارش ناموفق",

    "order_cancelled":
        "سفارش لغو شد",

    "waiting_for_support":
        "انتظار پشتیبانی",
}


PAYMENT_STATE_NAMES: Final[
    dict[str, str]
] = {
    "selecting_method":
        "انتخاب روش پرداخت",

    "waiting_for_transaction_hash":
        "انتظار شناسه تراکنش",

    "verifying_transaction":
        "بررسی تراکنش",

    "payment_confirmed":
        "پرداخت تایید شد",

    "payment_failed":
        "پرداخت ناموفق",

    "payment_expired":
        "پرداخت منقضی شد",
}


ADMIN_ORDER_STATE_NAMES: Final[
    dict[str, str]
] = {
    "searching_order":
        "جستجوی سفارش",

    "viewing_order":
        "مشاهده سفارش",

    "reviewing_owner_request":
        "بررسی درخواست خرید",

    "confirming_approval":
        "تایید نهایی مالک",

    "entering_reject_reason":
        "ثبت دلیل رد",

    "changing_order_status":
        "تغییر وضعیت سفارش",

    "entering_admin_note":
        "ثبت یادداشت ادمین",

    "resolving_provider_unknown":
        "بررسی وضعیت نامشخص MarketApp",

    "confirming_manual_refund":
        "تایید Refund دستی",

    "confirming_manual_completion":
        "تایید تکمیل دستی",
}


# ============================================================
# Helpers
# ============================================================

def _short_state_name(
    state_name: str | None,
) -> str:
    if not state_name:
        return ""

    return (
        str(state_name)
        .strip()
        .split(":")[-1]
    )


def get_order_state_name(
    state_name: str | None,
) -> str:
    """
    نام فارسی State کاربر.

    نمونه ورودی:
        OrderStates:waiting_for_target_account
    """
    short_name = (
        _short_state_name(
            state_name
        )
    )

    if not short_name:
        return "نامشخص"

    return ORDER_STATE_NAMES.get(
        short_name,
        short_name,
    )


def get_payment_state_name(
    state_name: str | None,
) -> str:
    short_name = (
        _short_state_name(
            state_name
        )
    )

    if not short_name:
        return "نامشخص"

    return PAYMENT_STATE_NAMES.get(
        short_name,
        short_name,
    )


def get_admin_order_state_name(
    state_name: str | None,
) -> str:
    short_name = (
        _short_state_name(
            state_name
        )
    )

    if not short_name:
        return "نامشخص"

    return ADMIN_ORDER_STATE_NAMES.get(
        short_name,
        short_name,
    )


def normalize_order_status(
    status: str | None,
) -> str:
    if not status:
        return ""

    return (
        str(status)
        .strip()
        .lower()
    )


def get_order_status_name(
    status: str | None,
) -> str:
    normalized = (
        normalize_order_status(
            status
        )
    )

    if not normalized:
        return "نامشخص"

    return ORDER_STATUS_NAMES.get(
        normalized,
        normalized,
    )


def is_valid_order_status(
    status: str | None,
) -> bool:
    normalized = (
        normalize_order_status(
            status
        )
    )

    return (
        bool(normalized)
        and normalized
        in ORDER_DB_STATUSES
    )


def is_terminal_order_status(
    status: str | None,
) -> bool:
    normalized = (
        normalize_order_status(
            status
        )
    )

    return (
        bool(normalized)
        and normalized
        in TERMINAL_STATUSES
    )


def requires_manual_review(
    status: str | None,
) -> bool:
    normalized = (
        normalize_order_status(
            status
        )
    )

    return (
        bool(normalized)
        and normalized
        in MANUAL_REVIEW_STATUSES
    )


# ============================================================
# Export
# ============================================================

__all__ = [
    # FSM
    "OrderStates",
    "PaymentStates",
    "AdminOrderStates",

    # DB Status
    "OrderStatus",
    "ORDER_DB_STATUSES",
    "OWNER_PENDING_STATUSES",
    "PROCESSING_STATUSES",
    "SUCCESS_STATUSES",
    "FAILURE_STATUSES",
    "MANUAL_REVIEW_STATUSES",
    "TERMINAL_STATUSES",

    # Labels
    "ORDER_STATUS_NAMES",
    "ORDER_STATE_NAMES",
    "PAYMENT_STATE_NAMES",
    "ADMIN_ORDER_STATE_NAMES",

    # Helpers
    "normalize_order_status",
    "get_order_status_name",
    "get_order_state_name",
    "get_payment_state_name",
    "get_admin_order_state_name",
    "is_valid_order_status",
    "is_terminal_order_status",
    "requires_manual_review",
]