"""Type definitions for the Pass payment SDK."""

from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional

# ============================================================================
# Status Constants
# ============================================================================

OrderInquiryStatusPaid = "paid"
OrderInquiryStatusPending = "pending"
OrderInquiryStatusCancelled = "cancelled"
OrderInquiryStatusVoided = "voided"

# ============================================================================
# Webhook Operation Constants
# ============================================================================

WebhookOperationPayment = "payment"
WebhookOperationVoid = "void"

# ============================================================================
# Configuration
# ============================================================================


@dataclass
class PassConfig:
    """Configuration for the PassClient.

    Attributes:
        endpoint: Base URL of the Pass API.
        ecommerce_token: E-commerce token for authentication.
        callback: Callback URL for order notifications.
    """

    endpoint: str
    ecommerce_token: str
    callback: str


# ============================================================================
# Base Error
# ============================================================================


@dataclass
class BaseError:
    """Base error structure returned by the Pass API.

    Attributes:
        code: Error code.
        level: Error level.
        body: Error body/message.
    """

    code: str
    level: str
    body: str


# ============================================================================
# Create Order
# ============================================================================


@dataclass
class RetCreateOrder:
    """Return value from creating an order.

    Attributes:
        shop: Shop name.
        amount: Order amount as string.
        order_id: The created order ID.
        order_ttl: Order time-to-live.
        db_ref_no: Database reference number.
    """

    shop: str
    amount: str
    order_id: str
    order_ttl: int
    db_ref_no: str


# ============================================================================
# Order Inquiry
# ============================================================================


@dataclass
class CustomerData:
    """Customer data from order inquiry.

    Attributes:
        user_id: User ID.
        unique_id: Unique identifier.
    """

    user_id: str
    unique_id: str


@dataclass
class LoyaltyData:
    """Loyalty data from order inquiry.

    Attributes:
        kb_status: KB status.
        kb_txn_id: KB transaction ID.
        kb_card_id: KB card ID.
        kb_usable_lp: KB usable loyalty points.
        kb_loyalty_pk: KB loyalty PK.
        has_kb_loyalty: Whether KB loyalty exists.
        kb_description: KB description.
        kb_limit_value: KB limit value.
        kb_loyalty_type: KB loyalty type.
        kb_dates_of_week: KB dates of week.
        kb_no_txn_amount: KB no-transaction amount.
        kb_yes_txn_amount: KB yes-transaction amount.
        kb_loyalty_provider_name: KB loyalty provider name.
    """

    kb_status: str
    kb_txn_id: str
    kb_card_id: str
    kb_usable_lp: str
    kb_loyalty_pk: str
    has_kb_loyalty: str
    kb_description: str
    kb_limit_value: str
    kb_loyalty_type: str
    kb_dates_of_week: str
    kb_no_txn_amount: str
    kb_yes_txn_amount: str
    kb_loyalty_provider_name: str


@dataclass
class ExtraData:
    """Extra data from order inquiry.

    Attributes:
        _id: ID.
        pan: PAN.
        rrn: RRN.
        amount: Amount.
        pos_id: POS ID.
        order_id: Order ID.
        resp_msg: Response message.
        trace_no: Trace number.
        date_time: Date/time.
        resp_code: Response code.
        terminal_id: Terminal ID.
        approved_code: Approved code.
        currency_code: Currency code.
        payment_request_id: Payment request ID.
    """

    _id: str
    pan: str
    rrn: str
    amount: str
    pos_id: str
    order_id: str
    resp_msg: str
    trace_no: str
    date_time: str
    resp_code: str
    terminal_id: str
    approved_code: str
    currency_code: str
    payment_request_id: str


@dataclass
class RetInquiryOrder:
    """Return value from order inquiry.

    Attributes:
        resp_code: Response code.
        resp_msg: Response message.
        status: Order status.
        amount: Order amount.
        db_ref_no: Database reference number.
        status_text: Status text.
        customer_data: Optional customer data.
        loyalty_data: Optional loyalty data.
        extra_data: Optional extra data.
    """

    resp_code: str
    resp_msg: str
    status: str
    amount: str
    db_ref_no: str
    status_text: str
    customer_data: Optional[CustomerData] = None
    loyalty_data: Optional[LoyaltyData] = None
    extra_data: Optional[ExtraData] = None


# ============================================================================
# Order Notify
# ============================================================================


@dataclass
class Datum:
    """Single notification result.

    Attributes:
        success: Whether the notification was successful.
        message_id: Message ID.
    """

    success: bool
    message_id: str


@dataclass
class RetNotifyOrder:
    """Return value from order notification.

    Attributes:
        resp_code: Response code.
        resp_msg: Response message.
        success: Success count.
        data: List of notification results.
    """

    resp_code: str
    resp_msg: str
    success: int
    data: List[Datum] = field(default_factory=list)


# ============================================================================
# Order Cancel
# ============================================================================


@dataclass
class RetOrderCancel:
    """Return value from order cancellation.

    Attributes:
        resp_code: Response code.
        resp_msg: Response message.
        status: Order status.
        amount: Order amount.
        loyalty_data: Loyalty data (may be any type).
        db_ref_no: Database reference number.
    """

    resp_code: str
    resp_msg: str
    status: str
    amount: str
    loyalty_data: Any
    db_ref_no: str


# ============================================================================
# Order Void
# ============================================================================


@dataclass
class RetOrderVoid:
    """Return value from order void.

    Attributes:
        resp_code: Response code.
        resp_msg: Response message.
        status: Order status.
        amount: Order amount.
        loyalty_data: Loyalty data (may be any type).
        db_ref_no: Database reference number.
        service_name: Service name.
        date_time: Date/time.
        trace_no: Trace number.
        rrn: RRN.
        terminal_id: Terminal ID.
        merchant_id: Merchant ID.
    """

    resp_code: str
    resp_msg: str
    status: str
    amount: str
    loyalty_data: Any
    db_ref_no: str
    service_name: str
    date_time: str
    trace_no: str
    rrn: str
    terminal_id: str
    merchant_id: str


# ============================================================================
# Webhook
# ============================================================================


@dataclass
class WebhookCallbackResponse:
    """Parsed webhook callback payload.

    Attributes:
        order_id: Order ID.
        payment_request_id: Payment request ID.
        pos_id: POS ID.
        operation: Operation type.
        is_success: Whether the operation was successful.
        amount: Amount.
        created_time: Created time.
        db_ref_no: Database reference number.
        customer_data: Optional customer data.
        extra_data: Optional extra data dictionary.
    """

    order_id: str
    payment_request_id: str
    pos_id: str
    operation: str
    is_success: bool
    amount: str
    created_time: str
    db_ref_no: str
    customer_data: Optional[CustomerData] = None
    extra_data: Optional[Dict[str, str]] = None
