"""
Loyalty program schemas for API requests and responses.
"""
from typing import Optional
from datetime import date, datetime
from pydantic import BaseModel, Field

from app.models.loyalty import LoyaltyTier, PointTransactionType


class LoyaltyMembershipBase(BaseModel):
    """Base loyalty membership schema."""
    tier: LoyaltyTier = LoyaltyTier.BRONZE
    notes: Optional[str] = None


class LoyaltyMembershipCreate(BaseModel):
    """Schema for creating a loyalty membership."""
    client_id: int
    establishment_id: int
    tier: LoyaltyTier = LoyaltyTier.BRONZE
    member_since: date = Field(default_factory=date.today)
    notes: Optional[str] = None


class LoyaltyMembershipUpdate(BaseModel):
    """Schema for updating a loyalty membership."""
    tier: Optional[LoyaltyTier] = None
    is_active: Optional[bool] = None
    notes: Optional[str] = None


class LoyaltyMembershipResponse(LoyaltyMembershipBase):
    """Schema for loyalty membership response."""
    id: int
    client_id: int
    establishment_id: int
    points_balance: int
    points_earned_lifetime: int
    points_redeemed_lifetime: int
    tier_points: int
    member_since: date
    tier_achieved_at: Optional[date] = None
    is_active: bool
    created_at: datetime
    updated_at: datetime

    # Computed property
    points_to_next_tier: int

    class Config:
        from_attributes = True


class PointTransactionBase(BaseModel):
    """Base point transaction schema."""
    points: int
    description: Optional[str] = None
    reference: Optional[str] = None


class PointTransactionCreate(BaseModel):
    """Schema for creating a point transaction."""
    membership_id: int
    transaction_type: PointTransactionType
    points: int
    reservation_id: Optional[int] = None
    description: Optional[str] = None
    reference: Optional[str] = None


class PointTransactionResponse(PointTransactionBase):
    """Schema for point transaction response."""
    id: int
    membership_id: int
    transaction_type: PointTransactionType
    balance_after: int
    reservation_id: Optional[int] = None
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


class LoyaltyRewardBase(BaseModel):
    """Base loyalty reward schema."""
    name: str = Field(..., max_length=200)
    name_en: Optional[str] = Field(None, max_length=200)
    description: Optional[str] = None
    points_required: int = Field(..., gt=0)
    category: Optional[str] = Field(None, max_length=100)
    is_active: bool = True
    terms: Optional[str] = None
    validity_days: int = Field(30, ge=1, le=365)


class LoyaltyRewardCreate(LoyaltyRewardBase):
    """Schema for creating a loyalty reward."""
    establishment_id: int


class LoyaltyRewardUpdate(BaseModel):
    """Schema for updating a loyalty reward."""
    name: Optional[str] = Field(None, max_length=200)
    name_en: Optional[str] = Field(None, max_length=200)
    description: Optional[str] = None
    points_required: Optional[int] = Field(None, gt=0)
    category: Optional[str] = Field(None, max_length=100)
    is_active: Optional[bool] = None
    terms: Optional[str] = None
    validity_days: Optional[int] = Field(None, ge=1, le=365)


class LoyaltyRewardResponse(LoyaltyRewardBase):
    """Schema for loyalty reward response."""
    id: int
    establishment_id: int
    created_at: datetime
    updated_at: datetime

    class Config:
        from_attributes = True


class EarnPointsRequest(BaseModel):
    """Schema for earning points."""
    points: int = Field(..., gt=0)
    reservation_id: Optional[int] = None
    description: Optional[str] = None
    reference: Optional[str] = None


class RedeemPointsRequest(BaseModel):
    """Schema for redeeming points."""
    points: int = Field(..., gt=0)
    reward_id: Optional[int] = None
    description: Optional[str] = None
    reference: Optional[str] = None


class LoyaltyStatistics(BaseModel):
    """Statistics for loyalty program."""
    total_members: int
    active_members: int
    inactive_members: int
    members_by_tier: dict[str, int]
    total_points_issued: int
    total_points_redeemed: int
    total_points_balance: int
    average_points_per_member: float
    top_tier_percentage: float
