from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from sqlalchemy import func, desc
from typing import Optional, List
from datetime import datetime, date
import logging
from ..config.database import get_db
from ..middleware.auth import get_current_user, authorize_roles
from ..models.user import User
from ..models.user_loyalty import UserLoyalty
from ..models.loyalty_tier import LoyaltyTier, TierLevel
from ..models.loyalty_point_transaction import LoyaltyPointTransaction, TransactionType, TransactionSource
from ..models.loyalty_reward import LoyaltyReward, RewardType, RewardStatus
from ..models.reward_redemption import RewardRedemption, RedemptionStatus
from ..models.referral import Referral, ReferralStatus
from ..services.loyalty_service import LoyaltyService
from pydantic import BaseModel, Field
from typing import Optional as Opt

logger = logging.getLogger(__name__)
router = APIRouter(prefix='/loyalty', tags=['loyalty'])

# Pydantic schemas for request/response
class UpdateUserLoyaltyRequest(BaseModel):
    birthday: Optional[str] = None
    anniversary_date: Optional[str] = None

class RedeemRewardRequest(BaseModel):
    reward_id: int
    booking_id: Optional[int] = None

class ApplyReferralRequest(BaseModel):
    referral_code: str

@router.get('/my-status')
async def get_my_loyalty_status(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get current user's loyalty status"""
    try:
        # Check if loyalty program is enabled
        from ..models.system_settings import SystemSettings
        setting = db.query(SystemSettings).filter(
            SystemSettings.key == 'loyalty_program_enabled'
        ).first()
        is_enabled = True  # Default to enabled
        if setting:
            is_enabled = setting.value.lower() == 'true'
        
        if not is_enabled:
            raise HTTPException(
                status_code=503,
                detail='Loyalty program is currently disabled'
            )
        user_loyalty = LoyaltyService.get_or_create_user_loyalty(db, current_user.id)
        
        tier = db.query(LoyaltyTier).filter(LoyaltyTier.id == user_loyalty.tier_id).first()
        
        # Get next tier
        next_tier = LoyaltyService.get_next_tier(db, tier) if tier else None
        
        # Calculate points needed for next tier
        points_needed = None
        if next_tier:
            points_needed = next_tier.min_points - user_loyalty.lifetime_points
        
        tier_dict = None
        if tier:
            tier_dict = {
                'id': tier.id,
                'level': tier.level.value if hasattr(tier.level, 'value') else tier.level,
                'name': tier.name,
                'description': tier.description,
                'points_earn_rate': float(tier.points_earn_rate) if tier.points_earn_rate else 1.0,
                'discount_percentage': float(tier.discount_percentage) if tier.discount_percentage else 0,
                'benefits': tier.benefits,
                'icon': tier.icon,
                'color': tier.color
            }
        
        next_tier_dict = None
        if next_tier:
            next_tier_dict = {
                'id': next_tier.id,
                'level': next_tier.level.value if hasattr(next_tier.level, 'value') else next_tier.level,
                'name': next_tier.name,
                'min_points': next_tier.min_points,
                'points_earn_rate': float(next_tier.points_earn_rate) if next_tier.points_earn_rate else 1.0,
                'discount_percentage': float(next_tier.discount_percentage) if next_tier.discount_percentage else 0,
                'points_needed': points_needed
            }
        
        return {
            'status': 'success',
            'data': {
                'total_points': user_loyalty.total_points,
                'lifetime_points': user_loyalty.lifetime_points,
                'available_points': user_loyalty.available_points,
                'expired_points': user_loyalty.expired_points,
                'referral_code': user_loyalty.referral_code,
                'referral_count': user_loyalty.referral_count,
                'birthday': user_loyalty.birthday.isoformat() if user_loyalty.birthday else None,
                'anniversary_date': user_loyalty.anniversary_date.isoformat() if user_loyalty.anniversary_date else None,
                'tier': tier_dict,
                'next_tier': next_tier_dict,
                'points_needed_for_next_tier': points_needed,
                'tier_started_date': user_loyalty.tier_started_date.isoformat() if user_loyalty.tier_started_date else None
            }
        }
    except HTTPException:
        # Re-raise HTTPException (like 503 for disabled program) without modification
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.get('/points/history')
async def get_points_history(
    page: int = Query(1, ge=1),
    limit: int = Query(20, ge=1, le=100),
    transaction_type: Optional[str] = Query(None),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get points transaction history"""
    try:
        user_loyalty = LoyaltyService.get_or_create_user_loyalty(db, current_user.id)
        
        query = db.query(LoyaltyPointTransaction).filter(
            LoyaltyPointTransaction.user_loyalty_id == user_loyalty.id
        )
        
        if transaction_type:
            try:
                query = query.filter(
                    LoyaltyPointTransaction.transaction_type == TransactionType(transaction_type)
                )
            except ValueError:
                pass
        
        total = query.count()
        offset = (page - 1) * limit
        transactions = query.order_by(desc(LoyaltyPointTransaction.created_at)).offset(offset).limit(limit).all()
        
        result = []
        for transaction in transactions:
            result.append({
                'id': transaction.id,
                'transaction_type': transaction.transaction_type.value if hasattr(transaction.transaction_type, 'value') else transaction.transaction_type,
                'source': transaction.source.value if hasattr(transaction.source, 'value') else transaction.source,
                'points': transaction.points,
                'description': transaction.description,
                'reference_number': transaction.reference_number,
                'expires_at': transaction.expires_at.isoformat() if transaction.expires_at else None,
                'created_at': transaction.created_at.isoformat() if transaction.created_at else None,
                'booking_id': transaction.booking_id
            })
        
        return {
            'status': 'success',
            'data': {
                'transactions': result,
                'pagination': {
                    'total': total,
                    'page': page,
                    'limit': limit,
                    'totalPages': (total + limit - 1) // limit
                }
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.put('/my-status')
async def update_my_loyalty_status(
    request: UpdateUserLoyaltyRequest,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Update user loyalty information (birthday, anniversary)"""
    try:
        user_loyalty = LoyaltyService.get_or_create_user_loyalty(db, current_user.id)
        
        # Store original values to detect if date actually changed
        original_birthday = user_loyalty.birthday
        original_anniversary = user_loyalty.anniversary_date
        
        birthday_changed = False
        anniversary_changed = False
        
        if request.birthday:
            try:
                new_birthday = datetime.fromisoformat(request.birthday).date()
                # Check if birthday actually changed
                if new_birthday != original_birthday:
                    birthday_changed = True
                    user_loyalty.birthday = new_birthday
            except ValueError:
                raise HTTPException(status_code=400, detail="Invalid birthday format. Use YYYY-MM-DD")
        
        if request.anniversary_date:
            try:
                new_anniversary = datetime.fromisoformat(request.anniversary_date).date()
                # Check if anniversary actually changed
                if new_anniversary != original_anniversary:
                    anniversary_changed = True
                    user_loyalty.anniversary_date = new_anniversary
            except ValueError:
                raise HTTPException(status_code=400, detail="Invalid anniversary date format. Use YYYY-MM-DD")
        
        db.commit()
        db.refresh(user_loyalty)
        
        # IMPORTANT: Only check for rewards if date was NOT just changed (prevent abuse)
        # If date was just changed, block rewards to prevent users from gaming the system
        # by repeatedly changing their birthday/anniversary to today's date
        if request.birthday and not birthday_changed:
            # Date wasn't changed, safe to check for rewards
            LoyaltyService.check_birthday_reward(db, current_user.id, prevent_recent_update=False)
        elif request.birthday and birthday_changed:
            # Date was just changed - block immediate rewards to prevent abuse
            logger.warning(f"Birthday reward blocked for user {current_user.id}: birthday was just updated")
        
        if request.anniversary_date and not anniversary_changed:
            # Date wasn't changed, safe to check for rewards
            LoyaltyService.check_anniversary_reward(db, current_user.id, prevent_recent_update=False)
        elif request.anniversary_date and anniversary_changed:
            # Date was just changed - block immediate rewards to prevent abuse
            logger.warning(f"Anniversary reward blocked for user {current_user.id}: anniversary was just updated")
        
        return {'status': 'success', 'message': 'Loyalty information updated successfully'}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

@router.get('/rewards')
async def get_available_rewards(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get available rewards for current user"""
    try:
        # Check if loyalty program is enabled
        from ..models.system_settings import SystemSettings
        setting = db.query(SystemSettings).filter(
            SystemSettings.key == 'loyalty_program_enabled'
        ).first()
        is_enabled = True  # Default to enabled
        if setting:
            is_enabled = setting.value.lower() == 'true'
        
        if not is_enabled:
            return {
                'status': 'success',
                'data': {
                    'rewards': [],
                    'available_points': 0,
                    'program_enabled': False
                }
            }
        user_loyalty = LoyaltyService.get_or_create_user_loyalty(db, current_user.id)
        
        rewards = db.query(LoyaltyReward).filter(LoyaltyReward.is_active == True).all()
        
        result = []
        for reward in rewards:
            # Get user's tier info for better availability checking
            user_tier = db.query(LoyaltyTier).filter(LoyaltyTier.id == user_loyalty.tier_id).first()
            user_tier_min_points = user_tier.min_points if user_tier else None
            
            # If reward requires a specific tier, pre-load tier info for comparison
            if reward.applicable_tier_id:
                required_tier = db.query(LoyaltyTier).filter(LoyaltyTier.id == reward.applicable_tier_id).first()
                if required_tier:
                    reward._required_tier_min_points = required_tier.min_points
            
            is_available = reward.is_available(user_loyalty.tier_id, user_tier_min_points)
            can_afford = user_loyalty.available_points >= reward.points_cost
            
            result.append({
                'id': reward.id,
                'name': reward.name,
                'description': reward.description,
                'reward_type': reward.reward_type.value if hasattr(reward.reward_type, 'value') else reward.reward_type,
                'points_cost': reward.points_cost,
                'discount_percentage': float(reward.discount_percentage) if reward.discount_percentage else None,
                'discount_amount': float(reward.discount_amount) if reward.discount_amount else None,
                'max_discount_amount': float(reward.max_discount_amount) if reward.max_discount_amount else None,
                'min_booking_amount': float(reward.min_booking_amount) if reward.min_booking_amount else None,
                'icon': reward.icon,
                'image': reward.image,
                'is_available': is_available,
                'can_afford': can_afford,
                'stock_remaining': reward.stock_quantity - reward.redeemed_count if reward.stock_quantity else None,
                'valid_from': reward.valid_from.isoformat() if reward.valid_from else None,
                'valid_until': reward.valid_until.isoformat() if reward.valid_until else None
            })
        
        return {
            'status': 'success',
            'data': {
                'rewards': result,
                'available_points': user_loyalty.available_points
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.post('/rewards/redeem')
async def redeem_reward(
    request: RedeemRewardRequest,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Redeem points for a reward"""
    try:
        # Check if loyalty program is enabled
        from ..models.system_settings import SystemSettings
        setting = db.query(SystemSettings).filter(
            SystemSettings.key == 'loyalty_program_enabled'
        ).first()
        is_enabled = True  # Default to enabled
        if setting:
            is_enabled = setting.value.lower() == 'true'
        
        if not is_enabled:
            raise HTTPException(
                status_code=503,
                detail='Loyalty program is currently disabled. Cannot redeem rewards.'
            )
        redemption = LoyaltyService.redeem_points(
            db,
            current_user.id,
            request.reward_id,
            request.booking_id
        )
        
        return {
            'status': 'success',
            'message': 'Reward redeemed successfully',
            'data': {
                'redemption_id': redemption.id,
                'code': redemption.code,
                'points_used': redemption.points_used,
                'status': redemption.status.value if hasattr(redemption.status, 'value') else redemption.status,
                'expires_at': redemption.expires_at.isoformat() if redemption.expires_at else None
            }
        }
    except HTTPException:
        # Re-raise HTTPException (like 503 for disabled program) without modification
        raise
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.get('/rewards/my-redemptions')
async def get_my_redemptions(
    status_filter: Optional[str] = Query(None),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get user's reward redemptions"""
    try:
        user_loyalty = LoyaltyService.get_or_create_user_loyalty(db, current_user.id)
        
        query = db.query(RewardRedemption).filter(
            RewardRedemption.user_loyalty_id == user_loyalty.id
        ).join(LoyaltyReward)
        
        if status_filter:
            try:
                query = query.filter(RewardRedemption.status == RedemptionStatus(status_filter))
            except ValueError:
                pass
        
        redemptions = query.order_by(desc(RewardRedemption.created_at)).all()
        
        result = []
        for redemption in redemptions:
            reward = redemption.reward
            result.append({
                'id': redemption.id,
                'reward': {
                    'id': reward.id,
                    'name': reward.name,
                    'description': reward.description,
                    'reward_type': reward.reward_type.value if hasattr(reward.reward_type, 'value') else reward.reward_type,
                    'discount_percentage': float(reward.discount_percentage) if reward.discount_percentage else None,
                    'discount_amount': float(reward.discount_amount) if reward.discount_amount else None,
                    'max_discount_amount': float(reward.max_discount_amount) if reward.max_discount_amount else None,
                    'min_booking_amount': float(reward.min_booking_amount) if reward.min_booking_amount else None
                },
                'points_used': redemption.points_used,
                'status': redemption.status.value if hasattr(redemption.status, 'value') else redemption.status,
                'code': redemption.code,
                'booking_id': redemption.booking_id,
                'expires_at': redemption.expires_at.isoformat() if redemption.expires_at else None,
                'used_at': redemption.used_at.isoformat() if redemption.used_at else None,
                'created_at': redemption.created_at.isoformat() if redemption.created_at else None
            })
        
        return {
            'status': 'success',
            'data': {
                'redemptions': result
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.post('/referral/apply')
async def apply_referral_code(
    request: ApplyReferralRequest,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Apply referral code (typically during registration or first booking)"""
    try:
        user_loyalty = LoyaltyService.get_or_create_user_loyalty(db, current_user.id)
        
        # Check if user already has referrals (can't use referral code if already referred)
        existing_referral = db.query(Referral).filter(
            Referral.referred_user_id == current_user.id
        ).first()
        
        if existing_referral:
            raise HTTPException(status_code=400, detail="You have already used a referral code")
        
        # Process referral (will be completed when booking is made)
        LoyaltyService.process_referral(
            db,
            current_user.id,
            request.referral_code,
            None  # No booking yet
        )
        
        return {
            'status': 'success',
            'message': 'Referral code applied successfully. You will receive bonus points when you complete your first booking.'
        }
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.get('/referral/my-referrals')
async def get_my_referrals(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """Get user's referrals (people they referred)"""
    try:
        user_loyalty = LoyaltyService.get_or_create_user_loyalty(db, current_user.id)
        
        referrals = db.query(Referral).filter(
            Referral.referrer_id == user_loyalty.id
        ).order_by(desc(Referral.created_at)).all()
        
        result = []
        for referral in referrals:
            referred_user = referral.referred_user
            result.append({
                'id': referral.id,
                'referred_user': {
                    'id': referred_user.id,
                    'name': referred_user.full_name,
                    'email': referred_user.email
                } if referred_user else None,
                'referral_code': referral.referral_code,
                'status': referral.status.value if hasattr(referral.status, 'value') else referral.status,
                'referrer_points_earned': referral.referrer_points_earned,
                'referred_points_earned': referral.referred_points_earned,
                'completed_at': referral.completed_at.isoformat() if referral.completed_at else None,
                'rewarded_at': referral.rewarded_at.isoformat() if referral.rewarded_at else None,
                'created_at': referral.created_at.isoformat() if referral.created_at else None
            })
        
        return {
            'status': 'success',
            'data': {
                'referrals': result,
                'total_referrals': len(result),
                'total_points_earned': sum(r.referrer_points_earned for r in referrals)
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# Admin routes - Program Control
@router.get('/admin/status')
async def get_loyalty_program_status(
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Get loyalty program enabled/disabled status"""
    try:
        from ..models.system_settings import SystemSettings
        setting = db.query(SystemSettings).filter(
            SystemSettings.key == 'loyalty_program_enabled'
        ).first()
        
        is_enabled = True  # Default to enabled
        if setting:
            is_enabled = setting.value.lower() == 'true'
        
        return {
            'status': 'success',
            'data': {
                'enabled': is_enabled,
                'updated_at': setting.updated_at.isoformat() if setting and setting.updated_at else None,
                'updated_by': setting.updated_by.full_name if setting and setting.updated_by else None
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.put('/admin/status')
async def update_loyalty_program_status(
    status_data: dict,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Enable/disable loyalty program"""
    try:
        from ..models.system_settings import SystemSettings
        enabled = status_data.get('enabled', True)
        
        setting = db.query(SystemSettings).filter(
            SystemSettings.key == 'loyalty_program_enabled'
        ).first()
        
        if setting:
            setting.value = str(enabled).lower()
            setting.updated_by_id = current_user.id
        else:
            setting = SystemSettings(
                key='loyalty_program_enabled',
                value=str(enabled).lower(),
                description='Enable or disable the loyalty program',
                updated_by_id=current_user.id
            )
            db.add(setting)
        
        db.commit()
        db.refresh(setting)
        
        return {
            'status': 'success',
            'message': f'Loyalty program {"enabled" if enabled else "disabled"} successfully',
            'data': {
                'enabled': enabled,
                'updated_at': setting.updated_at.isoformat() if setting.updated_at else None
            }
        }
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

# Admin routes - Tiers Management
@router.get('/admin/tiers')
async def get_all_tiers(
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Get all loyalty tiers (admin)"""
    try:
        tiers = db.query(LoyaltyTier).order_by(LoyaltyTier.min_points.asc()).all()
        
        result = []
        for tier in tiers:
            result.append({
                'id': tier.id,
                'level': tier.level.value if hasattr(tier.level, 'value') else tier.level,
                'name': tier.name,
                'description': tier.description,
                'min_points': tier.min_points,
                'points_earn_rate': float(tier.points_earn_rate) if tier.points_earn_rate else 1.0,
                'discount_percentage': float(tier.discount_percentage) if tier.discount_percentage else 0,
                'benefits': tier.benefits,
                'icon': tier.icon,
                'color': tier.color,
                'is_active': tier.is_active,
                'created_at': tier.created_at.isoformat() if tier.created_at else None,
                'updated_at': tier.updated_at.isoformat() if tier.updated_at else None
            })
        
        return {
            'status': 'success',
            'data': {
                'tiers': result
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.post('/admin/tiers')
async def create_tier(
    tier_data: dict,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Create a new loyalty tier"""
    try:
        # Check if tier level already exists
        existing = db.query(LoyaltyTier).filter(
            LoyaltyTier.level == TierLevel(tier_data['level'])
        ).first()
        if existing:
            raise HTTPException(status_code=400, detail=f"Tier level {tier_data['level']} already exists")
        
        tier = LoyaltyTier(
            level=TierLevel(tier_data['level']),
            name=tier_data['name'],
            description=tier_data.get('description'),
            min_points=tier_data.get('min_points', 0),
            points_earn_rate=tier_data.get('points_earn_rate', 1.0),
            discount_percentage=tier_data.get('discount_percentage', 0),
            benefits=tier_data.get('benefits'),
            icon=tier_data.get('icon'),
            color=tier_data.get('color'),
            is_active=tier_data.get('is_active', True)
        )
        db.add(tier)
        db.commit()
        db.refresh(tier)
        
        return {
            'status': 'success',
            'message': 'Tier created successfully',
            'data': {
                'id': tier.id,
                'level': tier.level.value if hasattr(tier.level, 'value') else tier.level,
                'name': tier.name
            }
        }
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

@router.put('/admin/tiers/{tier_id}')
async def update_tier(
    tier_id: int,
    tier_data: dict,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Update a loyalty tier"""
    try:
        tier = db.query(LoyaltyTier).filter(LoyaltyTier.id == tier_id).first()
        if not tier:
            raise HTTPException(status_code=404, detail='Tier not found')
        
        # Check if level is being changed and if new level exists
        if 'level' in tier_data and tier_data['level'] != tier.level.value:
            existing = db.query(LoyaltyTier).filter(
                LoyaltyTier.level == TierLevel(tier_data['level']),
                LoyaltyTier.id != tier_id
            ).first()
            if existing:
                raise HTTPException(status_code=400, detail=f"Tier level {tier_data['level']} already exists")
            tier.level = TierLevel(tier_data['level'])
        
        if 'name' in tier_data:
            tier.name = tier_data['name']
        if 'description' in tier_data:
            tier.description = tier_data['description']
        if 'min_points' in tier_data:
            tier.min_points = tier_data['min_points']
        if 'points_earn_rate' in tier_data:
            tier.points_earn_rate = tier_data['points_earn_rate']
        if 'discount_percentage' in tier_data:
            tier.discount_percentage = tier_data['discount_percentage']
        if 'benefits' in tier_data:
            tier.benefits = tier_data['benefits']
        if 'icon' in tier_data:
            tier.icon = tier_data['icon']
        if 'color' in tier_data:
            tier.color = tier_data['color']
        if 'is_active' in tier_data:
            tier.is_active = tier_data['is_active']
        
        db.commit()
        db.refresh(tier)
        
        return {
            'status': 'success',
            'message': 'Tier updated successfully',
            'data': {
                'id': tier.id,
                'level': tier.level.value if hasattr(tier.level, 'value') else tier.level,
                'name': tier.name
            }
        }
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

@router.delete('/admin/tiers/{tier_id}')
async def delete_tier(
    tier_id: int,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Delete a loyalty tier"""
    try:
        tier = db.query(LoyaltyTier).filter(LoyaltyTier.id == tier_id).first()
        if not tier:
            raise HTTPException(status_code=404, detail='Tier not found')
        
        # Check if any users are using this tier
        users_count = db.query(UserLoyalty).filter(UserLoyalty.tier_id == tier_id).count()
        if users_count > 0:
            raise HTTPException(
                status_code=400,
                detail=f'Cannot delete tier. {users_count} user(s) are currently assigned to this tier. Please reassign them first.'
            )
        
        db.delete(tier)
        db.commit()
        
        return {
            'status': 'success',
            'message': 'Tier deleted successfully'
        }
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

@router.get('/admin/users')
async def get_users_loyalty_status(
    search: Optional[str] = Query(None),
    tier_id: Optional[int] = Query(None),
    page: int = Query(1, ge=1),
    limit: int = Query(20, ge=1, le=100),
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Get all users' loyalty status (admin)"""
    try:
        query = db.query(UserLoyalty).join(User)
        
        if search:
            query = query.filter(
                User.full_name.like(f'%{search}%') |
                User.email.like(f'%{search}%')
            )
        
        if tier_id:
            query = query.filter(UserLoyalty.tier_id == tier_id)
        
        total = query.count()
        offset = (page - 1) * limit
        user_loyalties = query.order_by(desc(UserLoyalty.lifetime_points)).offset(offset).limit(limit).all()
        
        result = []
        for user_loyalty in user_loyalties:
            user = user_loyalty.user
            tier = user_loyalty.tier
            
            result.append({
                'user_id': user.id,
                'user_name': user.full_name,
                'user_email': user.email,
                'tier': {
                    'id': tier.id,
                    'name': tier.name,
                    'level': tier.level.value if hasattr(tier.level, 'value') else tier.level
                } if tier else None,
                'total_points': user_loyalty.total_points,
                'lifetime_points': user_loyalty.lifetime_points,
                'available_points': user_loyalty.available_points,
                'referral_count': user_loyalty.referral_count,
                'tier_started_date': user_loyalty.tier_started_date.isoformat() if user_loyalty.tier_started_date else None
            })
        
        return {
            'status': 'success',
            'data': {
                'users': result,
                'pagination': {
                    'total': total,
                    'page': page,
                    'limit': limit,
                    'totalPages': (total + limit - 1) // limit
                }
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# Admin routes - Rewards Management
@router.get('/admin/rewards')
async def get_all_rewards_admin(
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Get all rewards (admin)"""
    try:
        rewards = db.query(LoyaltyReward).order_by(LoyaltyReward.created_at.desc()).all()
        
        result = []
        for reward in rewards:
            result.append({
                'id': reward.id,
                'name': reward.name,
                'description': reward.description,
                'reward_type': reward.reward_type.value if hasattr(reward.reward_type, 'value') else reward.reward_type,
                'points_cost': reward.points_cost,
                'discount_percentage': float(reward.discount_percentage) if reward.discount_percentage else None,
                'discount_amount': float(reward.discount_amount) if reward.discount_amount else None,
                'max_discount_amount': float(reward.max_discount_amount) if reward.max_discount_amount else None,
                'applicable_tier_id': reward.applicable_tier_id,
                'min_booking_amount': float(reward.min_booking_amount) if reward.min_booking_amount else None,
                'icon': reward.icon,
                'image': reward.image,
                'is_active': reward.is_active,
                'stock_quantity': reward.stock_quantity,
                'redeemed_count': reward.redeemed_count,
                'valid_from': reward.valid_from.isoformat() if reward.valid_from else None,
                'valid_until': reward.valid_until.isoformat() if reward.valid_until else None,
                'created_at': reward.created_at.isoformat() if reward.created_at else None,
                'updated_at': reward.updated_at.isoformat() if reward.updated_at else None
            })
        
        return {
            'status': 'success',
            'data': {
                'rewards': result
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.post('/admin/rewards')
async def create_reward(
    reward_data: dict,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Create a new reward"""
    try:
        reward = LoyaltyReward(
            name=reward_data['name'],
            description=reward_data.get('description'),
            reward_type=RewardType(reward_data['reward_type']),
            points_cost=reward_data['points_cost'],
            discount_percentage=reward_data.get('discount_percentage'),
            discount_amount=reward_data.get('discount_amount'),
            max_discount_amount=reward_data.get('max_discount_amount'),
            applicable_tier_id=reward_data.get('applicable_tier_id'),
            min_booking_amount=reward_data.get('min_booking_amount'),
            icon=reward_data.get('icon'),
            image=reward_data.get('image'),
            is_active=reward_data.get('is_active', True),
            stock_quantity=reward_data.get('stock_quantity'),
            valid_from=datetime.fromisoformat(reward_data['valid_from']) if reward_data.get('valid_from') else None,
            valid_until=datetime.fromisoformat(reward_data['valid_until']) if reward_data.get('valid_until') else None
        )
        db.add(reward)
        db.commit()
        db.refresh(reward)
        
        return {
            'status': 'success',
            'message': 'Reward created successfully',
            'data': {
                'id': reward.id,
                'name': reward.name
            }
        }
    except ValueError as e:
        raise HTTPException(status_code=400, detail=f'Invalid reward type: {str(e)}')
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

@router.put('/admin/rewards/{reward_id}')
async def update_reward(
    reward_id: int,
    reward_data: dict,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Update a reward"""
    try:
        reward = db.query(LoyaltyReward).filter(LoyaltyReward.id == reward_id).first()
        if not reward:
            raise HTTPException(status_code=404, detail='Reward not found')
        
        if 'name' in reward_data:
            reward.name = reward_data['name']
        if 'description' in reward_data:
            reward.description = reward_data['description']
        if 'reward_type' in reward_data:
            reward.reward_type = RewardType(reward_data['reward_type'])
        if 'points_cost' in reward_data:
            reward.points_cost = reward_data['points_cost']
        if 'discount_percentage' in reward_data:
            reward.discount_percentage = reward_data['discount_percentage']
        if 'discount_amount' in reward_data:
            reward.discount_amount = reward_data['discount_amount']
        if 'max_discount_amount' in reward_data:
            reward.max_discount_amount = reward_data['max_discount_amount']
        if 'applicable_tier_id' in reward_data:
            reward.applicable_tier_id = reward_data['applicable_tier_id']
        if 'min_booking_amount' in reward_data:
            reward.min_booking_amount = reward_data['min_booking_amount']
        if 'icon' in reward_data:
            reward.icon = reward_data['icon']
        if 'image' in reward_data:
            reward.image = reward_data['image']
        if 'is_active' in reward_data:
            reward.is_active = reward_data['is_active']
        if 'stock_quantity' in reward_data:
            reward.stock_quantity = reward_data['stock_quantity']
        if 'valid_from' in reward_data:
            reward.valid_from = datetime.fromisoformat(reward_data['valid_from']) if reward_data['valid_from'] else None
        if 'valid_until' in reward_data:
            reward.valid_until = datetime.fromisoformat(reward_data['valid_until']) if reward_data['valid_until'] else None
        
        db.commit()
        db.refresh(reward)
        
        return {
            'status': 'success',
            'message': 'Reward updated successfully',
            'data': {
                'id': reward.id,
                'name': reward.name
            }
        }
    except HTTPException:
        raise
    except ValueError as e:
        raise HTTPException(status_code=400, detail=f'Invalid data: {str(e)}')
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

@router.delete('/admin/rewards/{reward_id}')
async def delete_reward(
    reward_id: int,
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Delete a reward"""
    try:
        reward = db.query(LoyaltyReward).filter(LoyaltyReward.id == reward_id).first()
        if not reward:
            raise HTTPException(status_code=404, detail='Reward not found')
        
        # Check if any redemptions exist
        redemptions_count = db.query(RewardRedemption).filter(RewardRedemption.reward_id == reward_id).count()
        if redemptions_count > 0:
            raise HTTPException(
                status_code=400,
                detail=f'Cannot delete reward. {redemptions_count} redemption(s) exist. Deactivate it instead.'
            )
        
        db.delete(reward)
        db.commit()
        
        return {
            'status': 'success',
            'message': 'Reward deleted successfully'
        }
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

