from fastapi import APIRouter, Request, Depends, Response, Security, encoders
import typing as t
from app.core.common import ApiReturnModel,ApiReturnPage
from app.core.apiexception import APIException
from app.core.dbmanager import get_db
from app.db.crud import (
    get_allusers,
    get_users,
    get_user,
    create_user,
    delete_user,
    edit_user,
    assign_userrole,
    get_roles,
)
from app.db.schemas import UserCreate, UserEdit, User, UserOut,RoleBase,AssignUserRoles,Permission
from app.core.auth import get_current_user,get_current_active_user, get_current_active_superuser
from app.db.cruddb import userService
from app.core import tenantCacheService

users_router = r = APIRouter()


@r.get(
    "/users",tags=["User"],
    response_model=ApiReturnPage[User],
    response_model_exclude_none=True,
)
async def users_list(
    request: Request,
    db=Depends(get_db),
    current_user=Depends(get_current_active_user),
):
    try:
        if current_user.is_superuser:
            users = userService.get_users(db)
        else:
            users = userService.get_users_not_admin(db)
        return users
    except Exception as e:
        raise APIException('user:users',request.url._url,f"Error occurred while get user list",e)

@r.get("/users/me", tags=["User"],
       response_model=ApiReturnModel[User], 
       response_model_exclude_none=True,
)
async def user_me(current_user=Depends(get_current_active_user)):
    return ApiReturnModel(data = current_user)


@r.get(
    "/users/{user_id}",tags=["User"],
    response_model=ApiReturnModel[User|None],
    response_model_exclude_none=True,
)
async def user_details(
    request: Request,
    user_id: int,
    db=Depends(get_db),
    current_user=Depends(get_current_active_user),
):
    try:
        user = userService.get(db, user_id)
        if user:
            if user.is_superuser and not current_user.is_superuser:
                user = None
        return ApiReturnModel(data = user)
    except Exception as e:
        raise APIException('user:users',request.url._url,f"Error occurred while get user({user_id}) detail:",e)


@r.post("/users", tags=["User"],
        response_model=ApiReturnModel[User|None], 
        response_model_exclude_none=True,
)
async def user_create(
    request: Request,
    user: UserCreate,
    db=Depends(get_db),
    current_user=Depends(get_current_active_user),
):
    try:
        if user.is_superuser and not current_user.is_superuser:
            return ApiReturnModel(data = None)
        return ApiReturnModel(data =userService.create_user(db, user,current_user.id))
    except Exception as e:
        raise APIException('user:users',request.url._url,f"Error occurred while create user({user.email}):",e)


@r.put(
    "/users/{user_id}", tags=["User"],
    response_model=ApiReturnModel[User|None],
    response_model_exclude_none=True,
)
async def user_edit(
    request: Request,
    user_id: int,
    user: UserEdit,
    db=Depends(get_db),
    current_user=Depends(get_current_active_user),
):
    try:
        if user.is_superuser and not current_user.is_superuser:
            return ApiReturnModel(data = None)
        return ApiReturnModel(data = userService.edit_user(db,user_id,user,current_user.id))
    except Exception as e:
        raise APIException('user:users',request.url._url,f"Error occurred while edit user({user_id}):",e)

@r.delete(
    "/users/{user_id}", tags=["User"],
    response_model=ApiReturnModel[UserOut|None], 
    response_model_exclude_none=True
)
async def user_delete(
    request: Request,
    user_id: int,
    db=Depends(get_db),
    current_user=Depends(get_current_active_user),
):
    try:
        user = userService.get(db,user_id)
        if user.is_superuser and not current_user.is_superuser:
            return ApiReturnModel(data = None)
        return ApiReturnModel(data = userService.delete_user(db, user_id))
    except Exception as e:
        raise APIException('user:users',request.url._url,f"Error occurred while delete user({user_id}):",e)


@r.post("/userrole",tags=["User"],
    response_model=ApiReturnModel[User],
    response_model_exclude_none=True,)
async def assign_role(
    request: Request,
    userroles:AssignUserRoles,
    db=Depends(get_db)
):
    try:
        return ApiReturnModel(data = userService.assign_userrole(db,userroles.userid,userroles.roleids))
    except Exception as e:
        raise APIException('user:userrole',request.url._url,f"Error occurred while assign user({userroles.userid}) roles({userroles.roleids}):",e)

@r.get(
    "/roles",tags=["User"],
    response_model=ApiReturnModel[t.List[RoleBase]|None],
    response_model_exclude_none=True,
)
async def roles_list(
    request: Request,
    db=Depends(get_db),
    current_user=Depends(get_current_active_user),
    #current_user=Security(get_current_active_user, scopes=["role_list"]),
):
    try:

        if current_user.is_superuser:
            roles = userService.get_roles(db)
        else:
            if len(current_user.roles)>0:
                roles = userService.get_roles_by_level(db,current_user.roles)
            else:
                roles = []
        return ApiReturnModel(data = roles)
    except Exception as e:
        raise APIException('user:roles',request.url._url,f"Error occurred while get roles:",e)

@r.get(
    "/userpermssions",tags=["User"],
    response_model=ApiReturnModel[t.List[Permission]|None],
    response_model_exclude_none=True,
)
async def permssions_list(
    request: Request,
    db=Depends(get_db),
    current_user=Depends(get_current_active_user),
    #current_user=Security(get_current_active_user, scopes=["role_list"]),
):
    try:
        if current_user.is_superuser:
            permissions = userService.get_permissions(db)
        else:
            if len(current_user.roles)>0:
                permissions = userService.get_user_permissions(db,current_user.id)
            else:
                permissions = []
        return ApiReturnModel(data = permissions)
    except Exception as e:
        raise APIException('user:userpermssions',request.url._url,f"Error occurred while get user({current_user.id}) permissions:",e)
