# app/modules/loyalty/schemas/card.py
"""
Pydantic schemas for loyalty card operations.

Merchant-based cards:
- Cards belong to a merchant's loyalty program
- One card per customer per merchant
- Can be used at any store within the merchant
"""

from datetime import date, datetime

from pydantic import BaseModel, ConfigDict, Field, field_validator


class CardEnrollRequest(BaseModel):
    """Schema for enrolling a customer in a loyalty program."""

    customer_id: int | None = Field(
        None,
        description="Customer ID (required for store API, optional for public enrollment)",
    )
    email: str | None = Field(
        None,
        description="Customer email (for public enrollment without customer_id)",
    )
    # Self-enrollment fields (used to create customer if not found)
    customer_name: str | None = Field(
        None, description="Full name for self-enrollment"
    )
    customer_phone: str | None = Field(
        None, description="Phone number for self-enrollment"
    )
    customer_birthday: date | None = Field(
        None, description="Birthday (YYYY-MM-DD) for self-enrollment"
    )

    @field_validator("customer_birthday")
    @classmethod
    def birthday_sane(cls, v: date | None) -> date | None:
        """Birthday must be in the past and within a plausible age range."""
        if v is None:
            return v
        today = date.today()
        if v >= today:
            raise ValueError("customer_birthday must be in the past")
        years = (today - v).days / 365.25
        if years < 13 or years > 120:
            raise ValueError("customer_birthday implies an implausible age")
        return v


class CardResponse(BaseModel):
    """Schema for loyalty card response (summary)."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    card_number: str
    customer_id: int
    merchant_id: int
    program_id: int
    enrolled_at_store_id: int | None = None

    # Customer info (for list views)
    customer_name: str | None = None
    customer_email: str | None = None

    # Stamps
    stamp_count: int
    stamps_target: int  # From program
    stamps_until_reward: int
    total_stamps_earned: int
    stamps_redeemed: int

    # Points
    points_balance: int
    total_points_earned: int
    points_redeemed: int

    # Status
    is_active: bool
    created_at: datetime

    # Wallet
    has_google_wallet: bool = False
    has_apple_wallet: bool = False


class CardDetailResponse(CardResponse):
    """Schema for detailed loyalty card response."""

    # QR code
    qr_code_data: str
    qr_code_url: str | None = None  # Generated QR code image URL

    # Customer info
    customer_name: str | None = None
    customer_email: str | None = None

    # Merchant info
    merchant_name: str | None = None
    enrolled_at_store_name: str | None = None

    # Program info
    program_name: str
    program_type: str
    reward_description: str | None = None

    # Activity
    last_stamp_at: datetime | None = None
    last_points_at: datetime | None = None
    last_redemption_at: datetime | None = None
    last_activity_at: datetime | None = None

    # Wallet URLs
    google_wallet_url: str | None = None
    apple_wallet_url: str | None = None


class CardListResponse(BaseModel):
    """Schema for listing loyalty cards."""

    cards: list[CardResponse]
    total: int


class CardLookupResponse(BaseModel):
    """Schema for card lookup by QR code or card number."""

    # Card info
    id: int
    card_number: str

    # Customer
    customer_id: int
    customer_name: str | None = None
    customer_email: str

    # Merchant context
    merchant_id: int
    merchant_name: str | None = None

    # Current balances
    stamp_count: int
    stamps_target: int
    stamps_until_reward: int
    points_balance: int

    # Can redeem?
    can_redeem_stamps: bool = False
    stamp_reward_description: str | None = None

    # Available points rewards
    available_rewards: list[dict] = []

    # Cooldown status
    can_stamp: bool = True
    cooldown_ends_at: datetime | None = None

    # Today's activity
    stamps_today: int = 0
    max_daily_stamps: int = 5
    can_earn_more_stamps: bool = True


class TransactionResponse(BaseModel):
    """Schema for a loyalty transaction."""

    model_config = ConfigDict(from_attributes=True)

    id: int
    card_id: int
    store_id: int | None = None
    store_name: str | None = None
    transaction_type: str

    # Deltas
    stamps_delta: int = 0
    points_delta: int = 0

    # Balances after
    stamps_balance_after: int | None = None
    points_balance_after: int | None = None

    # Context
    purchase_amount_cents: int | None = None
    order_reference: str | None = None
    reward_id: str | None = None
    reward_description: str | None = None
    category_ids: list[int] | None = None
    category_names: list[str] | None = None
    notes: str | None = None

    # Customer
    customer_name: str | None = None

    # Staff
    staff_name: str | None = None

    # Timestamps
    transaction_at: datetime
    created_at: datetime


class TransactionListResponse(BaseModel):
    """Schema for listing transactions."""

    transactions: list[TransactionResponse]
    total: int
