from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from sqlalchemy import or_
from typing import Optional
import bcrypt
from ..config.database import get_db
from ..middleware.auth import get_current_user, authorize_roles
from ..models.user import User
from ..models.role import Role
from ..models.booking import Booking, BookingStatus
router = APIRouter(prefix='/users', tags=['users'])

@router.get('/', dependencies=[Depends(authorize_roles('admin'))])
async def get_users(search: Optional[str]=Query(None), role: Optional[str]=Query(None), status_filter: Optional[str]=Query(None, alias='status'), page: int=Query(1, ge=1), limit: int=Query(10, ge=1, le=100), current_user: User=Depends(authorize_roles('admin')), db: Session=Depends(get_db)):
    try:
        query = db.query(User)
        if search:
            query = query.filter(or_(User.full_name.like(f'%{search}%'), User.email.like(f'%{search}%'), User.phone.like(f'%{search}%')))
        if role:
            role_map = {'admin': 1, 'staff': 2, 'customer': 3, 'accountant': 4}
            if role in role_map:
                query = query.filter(User.role_id == role_map[role])
        if status_filter:
            is_active = status_filter == 'active'
            query = query.filter(User.is_active == is_active)
        total = query.count()
        offset = (page - 1) * limit
        users = query.order_by(User.created_at.desc()).offset(offset).limit(limit).all()
        result = []
        for user in users:
            user_dict = {'id': user.id, 'email': user.email, 'full_name': user.full_name, 'phone': user.phone, 'phone_number': user.phone, 'address': user.address, 'avatar': user.avatar, 'currency': getattr(user, 'currency', 'VND'), 'is_active': user.is_active, 'status': 'active' if user.is_active else 'inactive', 'role_id': user.role_id, 'role': user.role.name if user.role else 'customer', 'created_at': user.created_at.isoformat() if user.created_at else None, 'updated_at': user.updated_at.isoformat() if user.updated_at else None}
            result.append(user_dict)
        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))

@router.get('/{id}', dependencies=[Depends(authorize_roles('admin'))])
async def get_user_by_id(id: int, current_user: User=Depends(authorize_roles('admin')), db: Session=Depends(get_db)):
    try:
        user = db.query(User).filter(User.id == id).first()
        if not user:
            raise HTTPException(status_code=404, detail='User not found')
        bookings = db.query(Booking).filter(Booking.user_id == id).order_by(Booking.created_at.desc()).limit(5).all()
        user_dict = {'id': user.id, 'email': user.email, 'full_name': user.full_name, 'phone': user.phone, 'phone_number': user.phone, 'address': user.address, 'avatar': user.avatar, 'currency': getattr(user, 'currency', 'VND'), 'is_active': user.is_active, 'status': 'active' if user.is_active else 'inactive', 'role_id': user.role_id, 'role': user.role.name if user.role else 'customer', 'created_at': user.created_at.isoformat() if user.created_at else None, 'updated_at': user.updated_at.isoformat() if user.updated_at else None, 'bookings': [{'id': b.id, 'booking_number': b.booking_number, 'status': b.status.value if isinstance(b.status, BookingStatus) else b.status, 'created_at': b.created_at.isoformat() if b.created_at else None} for b in bookings]}
        return {'status': 'success', 'data': {'user': user_dict}}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.post('/', dependencies=[Depends(authorize_roles('admin'))])
async def create_user(user_data: dict, current_user: User=Depends(authorize_roles('admin')), db: Session=Depends(get_db)):
    try:
        email = user_data.get('email')
        password = user_data.get('password')
        full_name = user_data.get('full_name')
        phone_number = user_data.get('phone_number')
        role = user_data.get('role', 'customer')
        status = user_data.get('status', 'active')
        role_map = {'admin': 1, 'staff': 2, 'customer': 3, 'accountant': 4}
        role_id = role_map.get(role, 3)
        existing = db.query(User).filter(User.email == email).first()
        if existing:
            raise HTTPException(status_code=400, detail='Email already exists')
        password_bytes = password.encode('utf-8')
        salt = bcrypt.gensalt()
        hashed_password = bcrypt.hashpw(password_bytes, salt).decode('utf-8')
        user = User(email=email, password=hashed_password, full_name=full_name, phone=phone_number, role_id=role_id, is_active=status == 'active')
        db.add(user)
        db.commit()
        db.refresh(user)
        user_dict = {'id': user.id, 'email': user.email, 'full_name': user.full_name, 'phone': user.phone, 'phone_number': user.phone, 'currency': getattr(user, 'currency', 'VND'), 'role_id': user.role_id, 'is_active': user.is_active}
        return {'status': 'success', 'message': 'User created successfully', 'data': {'user': user_dict}}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

@router.put('/{id}')
async def update_user(id: int, user_data: dict, current_user: User=Depends(get_current_user), db: Session=Depends(get_db)):
    try:
        if current_user.role_id != 1 and current_user.id != id:
            raise HTTPException(status_code=403, detail='Forbidden')
        user = db.query(User).filter(User.id == id).first()
        if not user:
            raise HTTPException(status_code=404, detail='User not found')
        email = user_data.get('email')
        if email and email != user.email:
            existing = db.query(User).filter(User.email == email).first()
            if existing:
                raise HTTPException(status_code=400, detail='Email already exists')
        role_map = {'admin': 1, 'staff': 2, 'customer': 3, 'accountant': 4}
        if 'full_name' in user_data:
            user.full_name = user_data['full_name']
        if 'email' in user_data and current_user.role_id == 1:
            user.email = user_data['email']
        if 'phone_number' in user_data:
            user.phone = user_data['phone_number']
        if 'role' in user_data and current_user.role_id == 1:
            user.role_id = role_map.get(user_data['role'], 3)
        if 'status' in user_data and current_user.role_id == 1:
            user.is_active = user_data['status'] == 'active'
        if 'currency' in user_data:
            currency = user_data['currency']
            if len(currency) == 3 and currency.isalpha():
                user.currency = currency.upper()
        if 'password' in user_data:
            password_bytes = user_data['password'].encode('utf-8')
            salt = bcrypt.gensalt()
            user.password = bcrypt.hashpw(password_bytes, salt).decode('utf-8')
        db.commit()
        db.refresh(user)
        user_dict = {'id': user.id, 'email': user.email, 'full_name': user.full_name, 'phone': user.phone, 'phone_number': user.phone, 'currency': getattr(user, 'currency', 'VND'), 'role_id': user.role_id, 'is_active': user.is_active}
        return {'status': 'success', 'message': 'User updated successfully', 'data': {'user': user_dict}}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))

@router.delete('/{id}', dependencies=[Depends(authorize_roles('admin'))])
async def delete_user(id: int, current_user: User=Depends(authorize_roles('admin')), db: Session=Depends(get_db)):
    try:
        user = db.query(User).filter(User.id == id).first()
        if not user:
            raise HTTPException(status_code=404, detail='User not found')
        active_bookings = db.query(Booking).filter(Booking.user_id == id, Booking.status.in_([BookingStatus.pending, BookingStatus.confirmed, BookingStatus.checked_in])).count()
        if active_bookings > 0:
            raise HTTPException(status_code=400, detail='Cannot delete user with active bookings')
        db.delete(user)
        db.commit()
        return {'status': 'success', 'message': 'User deleted successfully'}
    except HTTPException:
        raise
    except Exception as e:
        db.rollback()
        raise HTTPException(status_code=500, detail=str(e))