from typing import List, Optional
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, func

from app.database import get_db
from app.core.security import get_password_hash
from app.core.permissions import UserRole
from app.models.user import User
from app.models.tenant import Tenant
from app.schemas.user import UserCreate, UserUpdate, UserResponse
from app.schemas.common import PaginatedResponse, MessageResponse
from app.api.deps import get_current_user, require_permission, require_tenant_admin_or_above

router = APIRouter()


@router.get("", response_model=PaginatedResponse[UserResponse])
async def list_users(
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    tenant_id: Optional[UUID] = None,
    current_user: User = Depends(require_permission("users:read")),
    db: AsyncSession = Depends(get_db)
):
    """قائمة المستخدمين"""
    query = select(User)
    
    # Filter by tenant based on user role
    if current_user.role != UserRole.SUPER_ADMIN.value:
        query = query.where(User.tenant_id == current_user.tenant_id)
    elif tenant_id:
        query = query.where(User.tenant_id == tenant_id)
    
    # Count total
    count_query = select(func.count()).select_from(query.subquery())
    total = await db.scalar(count_query)
    
    # Paginate
    query = query.offset((page - 1) * page_size).limit(page_size)
    result = await db.execute(query)
    users = result.scalars().all()
    
    return PaginatedResponse(
        items=users,
        total=total,
        page=page,
        page_size=page_size,
        total_pages=(total + page_size - 1) // page_size
    )


@router.post("", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
async def create_user(
    user_data: UserCreate,
    current_user: User = Depends(require_permission("users:write")),
    db: AsyncSession = Depends(get_db)
):
    """إنشاء مستخدم جديد"""
    # Check if email exists
    result = await db.execute(select(User).where(User.email == user_data.email))
    if result.scalar_one_or_none():
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Email already registered"
        )
    
    # Validate tenant_id
    tenant_id = user_data.tenant_id
    if current_user.role != UserRole.SUPER_ADMIN.value:
        tenant_id = current_user.tenant_id
        # Tenant admins can only create tenant_user role
        if user_data.role not in [UserRole.TENANT_USER.value]:
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="You can only create tenant_user role"
            )
    
    user = User(
        email=user_data.email,
        password_hash=get_password_hash(user_data.password),
        full_name=user_data.full_name,
        full_name_ar=user_data.full_name_ar,
        phone=user_data.phone,
        role=user_data.role,
        tenant_id=tenant_id,
        language=user_data.language,
        timezone=user_data.timezone,
    )
    
    db.add(user)
    await db.commit()
    await db.refresh(user)
    
    return user


@router.get("/{user_id}", response_model=UserResponse)
async def get_user(
    user_id: UUID,
    current_user: User = Depends(require_permission("users:read")),
    db: AsyncSession = Depends(get_db)
):
    """الحصول على مستخدم محدد"""
    query = select(User).where(User.id == user_id)
    
    # Tenant users can only see users in their tenant
    if current_user.role != UserRole.SUPER_ADMIN.value:
        query = query.where(User.tenant_id == current_user.tenant_id)
    
    result = await db.execute(query)
    user = result.scalar_one_or_none()
    
    if user is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )
    
    return user


@router.patch("/{user_id}", response_model=UserResponse)
async def update_user(
    user_id: UUID,
    user_data: UserUpdate,
    current_user: User = Depends(require_permission("users:write")),
    db: AsyncSession = Depends(get_db)
):
    """تحديث مستخدم"""
    query = select(User).where(User.id == user_id)
    
    if current_user.role != UserRole.SUPER_ADMIN.value:
        query = query.where(User.tenant_id == current_user.tenant_id)
    
    result = await db.execute(query)
    user = result.scalar_one_or_none()
    
    if user is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )
    
    update_data = user_data.model_dump(exclude_unset=True)
    for field, value in update_data.items():
        setattr(user, field, value)
    
    await db.commit()
    await db.refresh(user)
    
    return user


@router.delete("/{user_id}", response_model=MessageResponse)
async def delete_user(
    user_id: UUID,
    current_user: User = Depends(require_permission("users:delete")),
    db: AsyncSession = Depends(get_db)
):
    """حذف مستخدم"""
    if user_id == current_user.id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Cannot delete yourself"
        )
    
    query = select(User).where(User.id == user_id)
    
    if current_user.role != UserRole.SUPER_ADMIN.value:
        query = query.where(User.tenant_id == current_user.tenant_id)
    
    result = await db.execute(query)
    user = result.scalar_one_or_none()
    
    if user is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )
    
    await db.delete(user)
    await db.commit()
    
    return MessageResponse(
        message="User deleted successfully",
        message_ar="تم حذف المستخدم بنجاح"
    )


@router.patch("/{user_id}/password", response_model=MessageResponse)
async def change_user_password(
    user_id: UUID,
    password_data: dict,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """تغيير كلمة مرور المستخدم"""
    from app.core.security import verify_password
    
    # Users can change their own password, admins can change others
    if user_id != current_user.id and current_user.role not in [UserRole.SUPER_ADMIN.value, UserRole.TENANT_ADMIN.value]:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not authorized to change this password"
        )
    
    query = select(User).where(User.id == user_id)
    if current_user.role == UserRole.TENANT_ADMIN.value and user_id != current_user.id:
        query = query.where(User.tenant_id == current_user.tenant_id)
    
    result = await db.execute(query)
    user = result.scalar_one_or_none()
    
    if user is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
    
    # If changing own password, verify current password
    if user_id == current_user.id and "current_password" in password_data:
        if not verify_password(password_data["current_password"], user.password_hash):
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Current password is incorrect")
    
    new_password = password_data.get("new_password")
    if not new_password or len(new_password) < 6:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Password must be at least 6 characters")
    
    user.password_hash = get_password_hash(new_password)
    await db.commit()
    
    return MessageResponse(
        message="Password changed successfully",
        message_ar="تم تغيير كلمة المرور بنجاح"
    )


@router.patch("/{user_id}/toggle-status", response_model=UserResponse)
async def toggle_user_status(
    user_id: UUID,
    current_user: User = Depends(require_permission("users:write")),
    db: AsyncSession = Depends(get_db)
):
    """تفعيل/إيقاف المستخدم"""
    if user_id == current_user.id:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Cannot toggle your own status"
        )
    
    query = select(User).where(User.id == user_id)
    if current_user.role != UserRole.SUPER_ADMIN.value:
        query = query.where(User.tenant_id == current_user.tenant_id)
    
    result = await db.execute(query)
    user = result.scalar_one_or_none()
    
    if user is None:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
    
    user.is_active = not user.is_active
    await db.commit()
    await db.refresh(user)
    
    return user
