"""
Gamification models for H2H betting platform
Includes: Tiers, XP, Achievements, Loot Boxes, Streaks
"""
from sqlalchemy import String, DateTime, Enum, Float, Integer, ForeignKey, Boolean, Text, JSON
from sqlalchemy.orm import Mapped, mapped_column, relationship
from datetime import datetime
import enum
from app.database import Base


class AchievementType(enum.Enum):
    """Types of achievements"""
    FIRST_BET = "first_bet"
    FIRST_WIN = "first_win"
    WIN_STREAK_3 = "win_streak_3"
    WIN_STREAK_5 = "win_streak_5"
    WIN_STREAK_10 = "win_streak_10"
    WHALE_BET = "whale_bet"  # Single bet over $1000
    HIGH_ROLLER = "high_roller"  # Total wagered over $10k
    CONSISTENT = "consistent"  # Bet every day for a week
    UNDERDOG = "underdog"  # Win 5 underdog bets
    SHARPSHOOTER = "sharpshooter"  # 70%+ win rate with 20+ bets
    VETERAN = "veteran"  # 100 total bets
    LEGEND = "legend"  # 500 total bets
    PROFIT_MASTER = "profit_master"  # $5000+ lifetime profit
    COMEBACK_KING = "comeback_king"  # Win after 5 loss streak
    EARLY_BIRD = "early_bird"  # Bet on event 24h+ before start
    SOCIAL_BUTTERFLY = "social_butterfly"  # Bet against 10 different users
    TIER_UP = "tier_up"  # Reach a new tier
    MAX_TIER = "max_tier"  # Reach tier 10


class LootBoxRarity(enum.Enum):
    """Loot box rarities"""
    COMMON = "common"
    UNCOMMON = "uncommon"
    RARE = "rare"
    EPIC = "epic"
    LEGENDARY = "legendary"


class LootBoxRewardType(enum.Enum):
    """Types of rewards from loot boxes"""
    BONUS_CASH = "bonus_cash"
    XP_BOOST = "xp_boost"
    FEE_REDUCTION = "fee_reduction"  # Temporary fee reduction
    FREE_BET = "free_bet"
    AVATAR_FRAME = "avatar_frame"
    BADGE = "badge"
    NOTHING = "nothing"  # Bad luck!


# Tier configuration: tier -> (min_xp, house_fee_percent, name)
TIER_CONFIG = {
    0: (0, 10.0, "Bronze I"),
    1: (1000, 9.5, "Bronze II"),
    2: (3000, 9.0, "Bronze III"),
    3: (7000, 8.5, "Silver I"),
    4: (15000, 8.0, "Silver II"),
    5: (30000, 7.5, "Silver III"),
    6: (60000, 7.0, "Gold I"),
    7: (100000, 6.5, "Gold II"),
    8: (175000, 6.0, "Gold III"),
    9: (300000, 5.5, "Platinum"),
    10: (500000, 5.0, "Diamond"),
}


class UserStats(Base):
    """Extended user statistics for gamification"""
    __tablename__ = "user_stats"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), unique=True)

    # XP and Tier
    xp: Mapped[int] = mapped_column(Integer, default=0)
    tier: Mapped[int] = mapped_column(Integer, default=0)

    # Detailed Stats
    total_wagered: Mapped[float] = mapped_column(Float, default=0.0)
    total_won: Mapped[float] = mapped_column(Float, default=0.0)
    total_lost: Mapped[float] = mapped_column(Float, default=0.0)
    net_profit: Mapped[float] = mapped_column(Float, default=0.0)
    biggest_win: Mapped[float] = mapped_column(Float, default=0.0)
    biggest_bet: Mapped[float] = mapped_column(Float, default=0.0)

    # Streaks
    current_win_streak: Mapped[int] = mapped_column(Integer, default=0)
    current_loss_streak: Mapped[int] = mapped_column(Integer, default=0)
    best_win_streak: Mapped[int] = mapped_column(Integer, default=0)
    worst_loss_streak: Mapped[int] = mapped_column(Integer, default=0)

    # Activity
    bets_today: Mapped[int] = mapped_column(Integer, default=0)
    bets_this_week: Mapped[int] = mapped_column(Integer, default=0)
    bets_this_month: Mapped[int] = mapped_column(Integer, default=0)
    consecutive_days_betting: Mapped[int] = mapped_column(Integer, default=0)
    last_bet_date: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)

    # Opponents
    unique_opponents: Mapped[int] = mapped_column(Integer, default=0)

    # Timestamps
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

    # Relationship
    user: Mapped["User"] = relationship(back_populates="stats")

    def get_house_fee(self) -> float:
        """Get the house fee percentage for this user's tier"""
        return TIER_CONFIG.get(self.tier, TIER_CONFIG[0])[1]

    def get_tier_name(self) -> str:
        """Get the display name for this user's tier"""
        return TIER_CONFIG.get(self.tier, TIER_CONFIG[0])[2]

    def xp_to_next_tier(self) -> int:
        """Get XP needed to reach the next tier"""
        if self.tier >= 10:
            return 0
        next_tier_xp = TIER_CONFIG[self.tier + 1][0]
        return max(0, next_tier_xp - self.xp)

    def tier_progress_percent(self) -> float:
        """Get progress percentage to next tier"""
        if self.tier >= 10:
            return 100.0
        current_tier_xp = TIER_CONFIG[self.tier][0]
        next_tier_xp = TIER_CONFIG[self.tier + 1][0]
        tier_xp_range = next_tier_xp - current_tier_xp
        xp_into_tier = self.xp - current_tier_xp
        return min(100.0, (xp_into_tier / tier_xp_range) * 100)


class Achievement(Base):
    """Achievement definitions"""
    __tablename__ = "achievements"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    type: Mapped[AchievementType] = mapped_column(Enum(AchievementType), unique=True)
    name: Mapped[str] = mapped_column(String(100))
    description: Mapped[str] = mapped_column(String(500))
    icon: Mapped[str] = mapped_column(String(50))  # Emoji or icon name
    xp_reward: Mapped[int] = mapped_column(Integer, default=100)
    rarity: Mapped[str] = mapped_column(String(20), default="common")  # common, rare, epic, legendary

    # Relationships
    user_achievements: Mapped[list["UserAchievement"]] = relationship(back_populates="achievement")


class UserAchievement(Base):
    """Tracks which achievements users have earned"""
    __tablename__ = "user_achievements"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
    achievement_id: Mapped[int] = mapped_column(ForeignKey("achievements.id"))
    earned_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    notified: Mapped[bool] = mapped_column(Boolean, default=False)

    # Relationships
    user: Mapped["User"] = relationship(back_populates="achievements")
    achievement: Mapped["Achievement"] = relationship(back_populates="user_achievements")


class LootBox(Base):
    """Loot box inventory for users"""
    __tablename__ = "loot_boxes"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
    rarity: Mapped[LootBoxRarity] = mapped_column(Enum(LootBoxRarity))
    source: Mapped[str] = mapped_column(String(50))  # How they got it: tier_up, achievement, daily, etc.
    opened: Mapped[bool] = mapped_column(Boolean, default=False)
    reward_type: Mapped[LootBoxRewardType | None] = mapped_column(Enum(LootBoxRewardType), nullable=True)
    reward_value: Mapped[str | None] = mapped_column(String(100), nullable=True)  # JSON or simple value
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    opened_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)

    # Relationship
    user: Mapped["User"] = relationship(back_populates="loot_boxes")


class ActivityFeed(Base):
    """Global activity feed for recent bets, wins, etc."""
    __tablename__ = "activity_feed"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
    activity_type: Mapped[str] = mapped_column(String(50))  # bet_placed, bet_won, achievement, tier_up, whale_bet
    message: Mapped[str] = mapped_column(String(500))
    extra_data: Mapped[str | None] = mapped_column(Text, nullable=True)  # JSON for extra data
    amount: Mapped[float | None] = mapped_column(Float, nullable=True)
    is_public: Mapped[bool] = mapped_column(Boolean, default=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)

    # Relationship
    user: Mapped["User"] = relationship(back_populates="activities")


class DailyReward(Base):
    """Daily login rewards"""
    __tablename__ = "daily_rewards"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
    day_streak: Mapped[int] = mapped_column(Integer, default=1)
    reward_type: Mapped[str] = mapped_column(String(50))  # xp, loot_box, bonus_cash
    reward_value: Mapped[str] = mapped_column(String(100))
    claimed_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)

    # Relationship
    user: Mapped["User"] = relationship(back_populates="daily_rewards")
