"""Pydantic v2 models for referral codes, events, rewards, and statistics."""

from __future__ import annotations

import enum
from datetime import datetime
from uuid import UUID

from pydantic import BaseModel, Field


class ReferralStatus(str, enum.Enum):
    """Lifecycle status of a referral event."""

    PENDING = "pending"
    COMPLETED = "completed"
    REWARDED = "rewarded"
    EXPIRED = "expired"


class RewardType(str, enum.Enum):
    """Type of reward granted for a successful referral."""

    CREDIT = "credit"
    DISCOUNT = "discount"
    FEATURE = "feature"
    CUSTOM = "custom"


class RewardStatus(str, enum.Enum):
    """Processing status of a referral reward."""

    PENDING = "pending"
    GRANTED = "granted"
    FAILED = "failed"


# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------


class ReferralConfig(BaseModel):
    """Program-level settings for the referral system.

    Controls reward behaviour, code limits, and expiration policy.
    """

    reward_type: RewardType = RewardType.CREDIT
    reward_amount: float = 10.0
    max_referrals_per_user: int = 50
    default_code_max_uses: int = 10
    expiry_days: int = 90
    double_sided: bool = True


# ---------------------------------------------------------------------------
# Core domain models
# ---------------------------------------------------------------------------


class ReferralCode(BaseModel):
    """A unique invite code linked to a referring user."""

    id: UUID
    code: str = Field(min_length=1, max_length=32)
    user_id: str
    uses: int = 0
    max_uses: int | None = None
    created_at: datetime
    expires_at: datetime | None = None
    active: bool = True


class Referral(BaseModel):
    """A single referral event tracking referrer to referred relationship."""

    id: UUID
    referrer_id: str
    referred_id: str
    code: str
    status: ReferralStatus = ReferralStatus.PENDING
    created_at: datetime
    completed_at: datetime | None = None
    metadata: dict = Field(default_factory=dict)


class ReferralReward(BaseModel):
    """Record of a reward granted for a successful referral."""

    id: UUID
    user_id: str
    referral_id: UUID
    reward_type: RewardType
    amount: float
    status: RewardStatus = RewardStatus.PENDING
    granted_at: datetime | None = None
    metadata: dict = Field(default_factory=dict)


# ---------------------------------------------------------------------------
# Aggregates / read models
# ---------------------------------------------------------------------------


class ReferralStats(BaseModel):
    """Aggregate referral statistics for a single user."""

    user_id: str
    total_referrals: int = 0
    completed: int = 0
    pending: int = 0
    expired: int = 0
    total_rewards_earned: float = 0.0


class LeaderboardEntry(BaseModel):
    """A single entry in the referral leaderboard."""

    user_id: str
    completed_referrals: int
    total_rewards: float


# ---------------------------------------------------------------------------
# API request / response helpers
# ---------------------------------------------------------------------------


class CreateCodeRequest(BaseModel):
    """Request body for creating a new referral code."""

    user_id: str
    max_uses: int | None = None


class ApplyReferralRequest(BaseModel):
    """Request body for applying a referral code."""

    code: str
    referred_user_id: str


class CompleteReferralRequest(BaseModel):
    """Request body for completing a referral."""

    referral_id: UUID
