"""
Gamification Router - XP, Levels, Leaderboards
"""
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import Session, select
from typing import List
from pydantic import BaseModel
from datetime import datetime

from database import get_session
from models import User, Badge, UserBadge
from routers.auth import get_current_user
from services.gamification import (
    calculate_level,
    xp_for_next_level,
    update_streak,
    check_and_award_badges,
    get_leaderboard,
    seed_badges,
    LEVEL_NAMES,
    XP_REWARDS,
)

router = APIRouter(prefix="/gamification", tags=["gamification"])


class LevelProgress(BaseModel):
    current_xp: int
    level: int
    level_name: str
    xp_for_next: int
    xp_progress: int
    progress_percent: float
    streak_days: int


class LeaderboardEntry(BaseModel):
    rank: int
    username: str
    xp: int
    level: int
    level_name: str
    streak: int


class BadgeResponse(BaseModel):
    id: int
    name: str
    description: str
    icon: str
    slug: str
    tier: str
    category: str
    awarded_at: datetime | None = None


class XPRewardsInfo(BaseModel):
    rewards: dict
    level_thresholds: List[int]
    level_names: dict


@router.get("/me", response_model=LevelProgress)
async def get_my_progress(
    current_user: User = Depends(get_current_user),
    session: Session = Depends(get_session)
):
    """Get current user's XP and level progress"""
    xp_needed, xp_progress = xp_for_next_level(current_user.xp)
    progress_percent = (xp_progress / xp_needed * 100) if xp_needed > 0 else 100
    
    return LevelProgress(
        current_xp=current_user.xp,
        level=current_user.level,
        level_name=LEVEL_NAMES.get(current_user.level, "Unknown"),
        xp_for_next=xp_needed,
        xp_progress=xp_progress,
        progress_percent=round(progress_percent, 1),
        streak_days=current_user.streak_days,
    )


@router.post("/activity")
async def record_activity(
    current_user: User = Depends(get_current_user),
    session: Session = Depends(get_session)
):
    """Record user activity and update streak"""
    streak = update_streak(session, current_user)
    new_badges = check_and_award_badges(session, current_user)
    session.commit()
    
    return {
        "streak_days": streak,
        "new_badges": [b.name for b in new_badges],
        "xp": current_user.xp,
        "level": current_user.level,
    }


@router.get("/leaderboard", response_model=List[LeaderboardEntry])
async def get_xp_leaderboard(
    limit: int = 10,
    session: Session = Depends(get_session)
):
    """Get top users by XP"""
    leaders = get_leaderboard(session, limit)
    
    return [
        LeaderboardEntry(
            rank=i + 1,
            username=l["email"],
            xp=l["xp"],
            level=l["level"],
            level_name=l["level_name"],
            streak=l["streak"],
        )
        for i, l in enumerate(leaders)
    ]


@router.get("/badges", response_model=List[BadgeResponse])
async def get_all_badges(session: Session = Depends(get_session)):
    """Get all available badges"""
    badges = session.exec(select(Badge).order_by(Badge.tier, Badge.category)).all()
    return [
        BadgeResponse(
            id=b.id,
            name=b.name,
            description=b.description,
            icon=b.icon,
            slug=b.slug,
            tier=b.tier,
            category=b.category,
        )
        for b in badges
    ]


@router.get("/badges/me", response_model=List[BadgeResponse])
async def get_my_badges(
    current_user: User = Depends(get_current_user),
    session: Session = Depends(get_session)
):
    """Get current user's earned badges"""
    user_badges = session.exec(
        select(UserBadge, Badge)
        .join(Badge)
        .where(UserBadge.user_id == current_user.id)
        .order_by(UserBadge.awarded_at.desc())
    ).all()
    
    return [
        BadgeResponse(
            id=b.id,
            name=b.name,
            description=b.description,
            icon=b.icon,
            slug=b.slug,
            tier=b.tier,
            category=b.category,
            awarded_at=ub.awarded_at,
        )
        for ub, b in user_badges
    ]


@router.get("/info", response_model=XPRewardsInfo)
async def get_xp_info():
    """Get XP reward values and level thresholds"""
    from services.gamification import LEVEL_THRESHOLDS
    
    return XPRewardsInfo(
        rewards=XP_REWARDS,
        level_thresholds=LEVEL_THRESHOLDS,
        level_names=LEVEL_NAMES,
    )


@router.post("/seed-badges")
async def seed_badge_data(
    current_user: User = Depends(get_current_user),
    session: Session = Depends(get_session)
):
    """Seed badge definitions (admin only)"""
    if current_user.role not in ["admin", "moderator"]:
        raise HTTPException(status_code=403, detail="Admin access required")
    
    seed_badges(session)
    return {"message": "Badges seeded successfully"}


# ==========================================
# TITLE/FLAIR SHOP ENDPOINTS
# ==========================================

from services.gamification import (
    get_available_titles,
    get_available_colors,
    get_available_flairs,
    purchase_title,
    purchase_color,
    purchase_flair,
    get_user_display,
    EARLY_ADOPTER_PERKS,
)


class ShopItem(BaseModel):
    name: str
    type: str
    cost: int
    level_required: int
    is_owned: bool = False


class PurchaseRequest(BaseModel):
    item_name: str


@router.get("/shop/titles")
async def get_title_shop(
    current_user: User = Depends(get_current_user),
    session: Session = Depends(get_session)
):
    """Get available titles for purchase"""
    available = get_available_titles(current_user)
    
    return {
        "current_title": current_user.custom_title,
        "current_xp": current_user.xp,
        "items": [
            {
                "name": title,
                "type": info["type"],
                "cost": info["cost"],
                "level_required": info["level_required"],
                "is_owned": current_user.custom_title == title,
            }
            for title, info in available.items()
        ]
    }


@router.post("/shop/titles/purchase")
async def buy_title(
    request: PurchaseRequest,
    current_user: User = Depends(get_current_user),
    session: Session = Depends(get_session)
):
    """Purchase a title with XP"""
    success, message = purchase_title(session, current_user, request.item_name)
    
    if not success:
        raise HTTPException(status_code=400, detail=message)
    
    return {
        "success": True,
        "message": message,
        "new_title": current_user.custom_title,
        "remaining_xp": current_user.xp,
    }


@router.get("/shop/colors")
async def get_color_shop(
    current_user: User = Depends(get_current_user),
    session: Session = Depends(get_session)
):
    """Get available username colors for purchase"""
    available = get_available_colors(current_user)
    
    return {
        "current_color": current_user.title_color,
        "current_xp": current_user.xp,
        "items": [
            {
                "name": name,
                "hex": info["hex"],
                "cost": info["cost"],
                "is_owned": current_user.title_color == info["hex"],
            }
            for name, info in available.items()
        ]
    }


@router.post("/shop/colors/purchase")
async def buy_color(
    request: PurchaseRequest,
    current_user: User = Depends(get_current_user),
    session: Session = Depends(get_session)
):
    """Purchase a username color with XP"""
    success, message = purchase_color(session, current_user, request.item_name)
    
    if not success:
        raise HTTPException(status_code=400, detail=message)
    
    return {
        "success": True,
        "message": message,
        "new_color": current_user.title_color,
        "remaining_xp": current_user.xp,
    }


@router.get("/shop/flairs")
async def get_flair_shop(
    current_user: User = Depends(get_current_user),
    session: Session = Depends(get_session)
):
    """Get available flairs for purchase"""
    available = get_available_flairs(current_user)
    
    return {
        "current_flair": current_user.flair,
        "current_xp": current_user.xp,
        "items": [
            {
                "name": flair,
                "cost": info["cost"],
                "is_owned": current_user.flair == flair,
            }
            for flair, info in available.items()
        ]
    }


@router.post("/shop/flairs/purchase")
async def buy_flair(
    request: PurchaseRequest,
    current_user: User = Depends(get_current_user),
    session: Session = Depends(get_session)
):
    """Purchase a flair with XP"""
    success, message = purchase_flair(session, current_user, request.item_name)
    
    if not success:
        raise HTTPException(status_code=400, detail=message)
    
    return {
        "success": True,
        "message": message,
        "new_flair": current_user.flair,
        "remaining_xp": current_user.xp,
    }


@router.get("/user/{user_id}/display")
async def get_user_display_info(
    user_id: int,
    session: Session = Depends(get_session)
):
    """Get a user's display info (title, color, flair)"""
    user = session.get(User, user_id)
    if not user:
        raise HTTPException(status_code=404, detail="User not found")
    
    return get_user_display(user)


@router.get("/early-adopter-perks")
async def get_early_adopter_info():
    """Get information about early adopter perks"""
    return {
        "perks": EARLY_ADOPTER_PERKS,
        "description": "The first 100 users get exclusive perks including unique titles, colors, "
                       "and a 10% XP bonus on all actions!"
    }

