"""Receipt-related models."""

from typing import Literal

from pydantic import BaseModel, Field


class ReceiptItem(BaseModel):
    """Receipt item."""

    description: str = Field(..., description="Description of the purchased product")
    amount: int = Field(
        ...,
        description=(
            "Amount in minor units of the currency, "
            "eg. pennies for GBP, or cents for EUR and USD"
        ),
    )
    currency: str = Field(..., description="ISO 4217 currency code")
    quantity: float | None = Field(
        None, description="Quantity purchased (supports decimals for weights)"
    )
    unit: str | None = Field(
        None, description="Unit of measurement (e.g., 'kg', 'pieces')"
    )
    tax: int | None = Field(
        None,
        description=(
            "Tax amount in minor units of the currency, "
            "eg. pennies for GBP, or cents for EUR and USD"
        ),
    )
    sub_items: list["ReceiptItem"] | None = Field(
        None, description="Sub-items (e.g., extras, modifications)"
    )


class ReceiptTax(BaseModel):
    """Receipt tax."""

    description: str = Field(..., description="Tax description (e.g., 'VAT')")
    amount: int = Field(
        ...,
        description=(
            "Tax amount in minor units of the currency, "
            "eg. pennies for GBP, or cents for EUR and USD"
        ),
    )
    currency: str = Field(..., description="ISO 4217 currency code")
    tax_number: str | None = Field(None, description="Tax registration number")


class ReceiptPayment(BaseModel):
    """Receipt payment."""

    type: Literal["card", "cash", "gift_card"] = Field(
        ..., description="Payment method type"
    )
    amount: int = Field(
        ...,
        description=(
            "Payment amount in minor units of the currency, "
            "eg. pennies for GBP, or cents for EUR and USD"
        ),
    )
    currency: str = Field(..., description="ISO 4217 currency code")
    bin: str | None = Field(
        None, description="Bank Identification Number (for card payments)"
    )
    last_four: str | None = Field(None, description="Last four digits of card number")
    auth_code: str | None = Field(
        None, description="Authorisation code for card payment"
    )
    aid: str | None = Field(None, description="Application Identifier")
    mid: str | None = Field(None, description="Merchant Identifier")
    tid: str | None = Field(None, description="Terminal Identifier")
    gift_card_type: str | None = Field(
        None, description="Type of gift card (for gift card payments)"
    )


class ReceiptMerchant(BaseModel):
    """Receipt merchant information."""

    name: str | None = Field(None, description="Merchant name")
    online: bool | None = Field(
        None,
        description=(
            "Whether this is an online merchant (true) or physical store (false)"
        ),
    )
    phone: str | None = Field(None, description="Merchant contact phone number")
    email: str | None = Field(None, description="Merchant contact email address")
    store_name: str | None = Field(
        None, description="Specific store name (e.g., 'Old Street')"
    )
    store_address: str | None = Field(None, description="Physical store address")
    store_postcode: str | None = Field(None, description="Store postcode")


class Receipt(BaseModel):
    """Represents a receipt."""

    id: str | None = Field(
        None, description="Unique receipt identifier (generated by Monzo)"
    )
    external_id: str = Field(
        ..., description="External identifier (used as idempotency key)"
    )
    transaction_id: str = Field(..., description="ID of the associated transaction")
    total: int = Field(
        ...,
        description=(
            "Total amount in minor units of the currency, "
            "eg. pennies for GBP, or cents for EUR and USD"
        ),
    )
    currency: str = Field(..., description="ISO 4217 currency code")
    items: list[ReceiptItem] = Field(..., description="List of purchased items")
    taxes: list[ReceiptTax] | None = Field(None, description="List of taxes applied")
    payments: list[ReceiptPayment] | None = Field(
        None, description="List of payment methods used"
    )
    merchant: ReceiptMerchant | None = Field(
        None, description="Merchant information for the receipt"
    )


# Response containers
class ReceiptResponse(BaseModel):
    """Receipt response."""

    receipt: Receipt = Field(..., description="Receipt object")


# Update forward references
ReceiptItem.model_rebuild()
