from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import func as sql_func
from datetime import datetime
from typing import List
from ..database import get_db
from ..models import User, ReferralReward, SystemSettings
from ..schemas import (
    ReferralRewardResponse, ReferralStats,
    ReferralSettingsResponse, ReferralSettingsUpdate,
)
from .auth import get_current_user
from .notification import notify_referral_reward

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


def get_referral_settings(db: Session) -> SystemSettings:
    """Get or create system settings"""
    settings = db.query(SystemSettings).first()
    if not settings:
        settings = SystemSettings()
        db.add(settings)
        db.commit()
        db.refresh(settings)
    return settings


def create_referral_reward(
    referrer_id: int,
    referred_user_id: int,
    payment_amount: float,
    db: Session
):
    """Create a referral reward when a referred user makes a payment"""
    settings = get_referral_settings(db)

    # Check if referral rewards are enabled
    if not settings.referral_reward_enabled:
        return None

    # Check if this is a one_time reward and already exists
    if settings.referral_reward_type == "one_time":
        existing = db.query(ReferralReward).filter(
            ReferralReward.referrer_id == referrer_id,
            ReferralReward.referred_user_id == referred_user_id
        ).first()
        if existing:
            return None  # Already gave reward for this referral

    # Calculate reward amount
    reward_amount = payment_amount * (settings.referral_reward_percent / 100)

    # Create reward record
    reward = ReferralReward(
        referrer_id=referrer_id,
        referred_user_id=referred_user_id,
        payment_amount=payment_amount,
        reward_amount=reward_amount,
        status="credited",  # Auto-credit for simplicity
        credited_at=datetime.utcnow()
    )

    db.add(reward)
    db.commit()
    db.refresh(reward)

    # Send notification to referrer
    referred_user = db.query(User).filter(User.id == referred_user_id).first()
    referred_name = referred_user.name or referred_user.email if referred_user else "회원"
    notify_referral_reward(db, referrer_id, reward_amount, referred_name)

    return reward


@router.get("/my-link")
def get_my_referral_link(current_user: User = Depends(get_current_user)):
    """Get current user's referral link/code"""
    return {
        "referral_code": current_user.referral_code,
        "referral_link": f"/register?ref={current_user.referral_code}"
    }


@router.get("/my-rewards", response_model=List[ReferralRewardResponse])
def get_my_rewards(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get current user's referral rewards"""
    rewards = db.query(ReferralReward).filter(
        ReferralReward.referrer_id == current_user.id
    ).order_by(ReferralReward.created_at.desc()).all()

    return rewards


@router.get("/stats", response_model=ReferralStats)
def get_referral_stats(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get referral statistics for current user"""
    # Get all rewards where user is the referrer
    rewards = db.query(ReferralReward).filter(
        ReferralReward.referrer_id == current_user.id
    ).all()

    # Count unique referred users
    referred_users = db.query(sql_func.count(sql_func.distinct(ReferralReward.referred_user_id))).filter(
        ReferralReward.referrer_id == current_user.id
    ).scalar() or 0

    total_rewards_earned = sum(r.reward_amount for r in rewards)
    total_rewards_credited = sum(r.reward_amount for r in rewards if r.status == "credited")
    total_rewards_pending = sum(r.reward_amount for r in rewards if r.status == "pending")
    total_withdrawn = sum(r.reward_amount for r in rewards if r.status == "withdrawn")

    return ReferralStats(
        total_referrals=referred_users,
        total_rewards_earned=total_rewards_earned,
        total_rewards_credited=total_rewards_credited,
        total_rewards_pending=total_rewards_pending,
        available_for_withdrawal=total_rewards_credited - total_withdrawn
    )


@router.get("/settings", response_model=ReferralSettingsResponse)
def get_settings(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get referral settings (public endpoint)"""
    settings = get_referral_settings(db)

    return ReferralSettingsResponse(
        referral_reward_enabled=settings.referral_reward_enabled,
        referral_reward_percent=settings.referral_reward_percent,
        referral_reward_type=settings.referral_reward_type
    )


# Admin endpoints
@router.put("/admin/settings", response_model=ReferralSettingsResponse)
def update_settings(
    update_data: ReferralSettingsUpdate,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """[Admin] Update referral settings"""
    if not current_user.is_admin:
        raise HTTPException(status_code=403, detail="Admin access required")

    settings = get_referral_settings(db)

    if update_data.referral_reward_enabled is not None:
        settings.referral_reward_enabled = update_data.referral_reward_enabled

    if update_data.referral_reward_percent is not None:
        if update_data.referral_reward_percent < 0 or update_data.referral_reward_percent > 100:
            raise HTTPException(status_code=400, detail="Reward percent must be between 0 and 100")
        settings.referral_reward_percent = update_data.referral_reward_percent

    if update_data.referral_reward_type is not None:
        if update_data.referral_reward_type not in ["one_time", "recurring"]:
            raise HTTPException(status_code=400, detail="Reward type must be 'one_time' or 'recurring'")
        settings.referral_reward_type = update_data.referral_reward_type

    db.commit()
    db.refresh(settings)

    return ReferralSettingsResponse(
        referral_reward_enabled=settings.referral_reward_enabled,
        referral_reward_percent=settings.referral_reward_percent,
        referral_reward_type=settings.referral_reward_type
    )


@router.get("/admin/all-rewards", response_model=List[ReferralRewardResponse])
def admin_get_all_rewards(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """[Admin] Get all referral rewards"""
    if not current_user.is_admin:
        raise HTTPException(status_code=403, detail="Admin access required")

    rewards = db.query(ReferralReward).order_by(
        ReferralReward.created_at.desc()
    ).limit(100).all()

    return rewards
