from typing import Optional
from app.schemas.common import (
    IDeleteResponseBase,
    IGetResponseBase,
    IPostResponseBase,
)
from fastapi_pagination import Page, Params
from app.schemas.user import IUserCreate, IUserRead, IUserReadWithoutGroups, IUserStatus
from sqlmodel.ext.asyncio.session import AsyncSession
from fastapi import APIRouter, Depends, HTTPException, Query
from app.api import deps
from app import crud
from app.models import User
from sqlmodel import select, and_
from uuid import UUID
from app.schemas.role import IRoleEnum
from app.models.role import Role

router = APIRouter()


@router.get("/user/list", response_model=IGetResponseBase[Page[IUserReadWithoutGroups]])
async def read_users_list(    
    params: Params = Depends(),
    db_session: AsyncSession = Depends(deps.get_db),
    current_user: User = Depends(deps.get_current_user(required_roles=[IRoleEnum.admin, IRoleEnum.manager])),
):
    """
    Retrieve users.
    """    
    users = await crud.user.get_multi_paginated(db_session, params=params)
    return IGetResponseBase[Page[IUserReadWithoutGroups]](data=users)

@router.get("/user/list/by_role_name", response_model=IGetResponseBase[Page[IUserReadWithoutGroups]])
async def read_users_list(
    status: Optional[IUserStatus] = Query(default=None, description="User status, It is optional"),
    role_name : str = Query(default='', description="String compare with name or last name"),
    params: Params = Depends(),
    db_session: AsyncSession = Depends(deps.get_db),
    current_user: User = Depends(deps.get_current_user(required_roles=[IRoleEnum.admin])),
):
    """
    Retrieve users by role name.
    """
    user_status = True if status == IUserStatus.active else False
    query = select(User).join(Role, User.role_id == Role.id).where(and_(Role.name == role_name, User.is_active == user_status)).order_by(User.first_name)
    users = await crud.user.get_multi_paginated(db_session, query=query, params=params)
    return IGetResponseBase[Page[IUserReadWithoutGroups]](data=users)

@router.get("/user/order_by_created_at", response_model=IGetResponseBase[Page[IUserReadWithoutGroups]])
async def get_hero_list_order_by_created_at(
    params: Params = Depends(),
    db_session: AsyncSession = Depends(deps.get_db),
    current_user: User = Depends(deps.get_current_user(required_roles=[IRoleEnum.admin, IRoleEnum.manager])),
):
    query = select(User).order_by(User.created_at)
    users = await crud.user.get_multi_paginated(db_session, query=query, params=params)
    return IGetResponseBase[Page[IUserReadWithoutGroups]](data=users)

@router.get("/user/{user_id}", response_model=IGetResponseBase[IUserRead])
async def get_user_by_id(
    user_id: UUID,
    db_session: AsyncSession = Depends(deps.get_db),
    current_user: User = Depends(deps.get_current_user(required_roles=[IRoleEnum.admin, IRoleEnum.manager])),
):
    user = await crud.user.get_user_by_id(db_session, id=user_id)
    return IGetResponseBase[IUserRead](data=user)

@router.get("/user", response_model=IGetResponseBase[IUserRead])
async def get_my_data(
    current_user: User = Depends(deps.get_current_user()),
):
    return IGetResponseBase[IUserRead](data=current_user)

@router.post("/user", response_model=IPostResponseBase[IUserRead])
async def create_user(
    new_user: IUserCreate,
    db_session: AsyncSession = Depends(deps.get_db),
    current_user: User = Depends(deps.get_current_user(required_roles=[IRoleEnum.admin])),
):    
    user = await crud.user.get_by_email(db_session, email=new_user.email)
    if user:
        raise HTTPException(status_code=404, detail="There is already a user with same email")
    user = await crud.user.create_with_role(db_session, obj_in=new_user)
    return IPostResponseBase[IUserRead](data=user)


@router.delete("/user/{user_id}", response_model=IDeleteResponseBase[IUserRead])
async def remove_user(
    user_id: UUID,
    db_session: AsyncSession = Depends(deps.get_db),
    current_user: User = Depends(deps.get_current_user(required_roles=[IRoleEnum.admin])),
):
    if current_user.id == user_id:
        raise HTTPException(status_code=404, detail="Users can not delete theirselfs")

    user = await crud.user.get_user_by_id(db_session=db_session, id=user_id)
    if not user:
        raise HTTPException(status_code=404, detail="User no found")    
    user = await crud.user.remove(db_session, id=user_id)
    return IDeleteResponseBase[IUserRead](
        data=user
    )

app.crud.user.remove app.crud.user.get_user_by_id fastapi.HTTPException sqlmodel.and_ app.crud.user.get_multi_paginated app.crud.user.get_by_email sqlmodel.select app.api.deps.get_current_user fastapi.APIRouter app.crud.user.create_with_role fastapi.Query fastapi.Depends
[((593, 604), 'fastapi.APIRouter', 'APIRouter', ([], {}), '()\n', (602, 604), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((748, 757), 'fastapi.Depends', 'Depends', ([], {}), '()\n', (755, 757), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((790, 810), 'fastapi.Depends', 'Depends', (['deps.get_db'], {}), '(deps.get_db)\n', (797, 810), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((1276, 1338), 'fastapi.Query', 'Query', ([], {'default': 'None', 'description': '"""User status, It is optional"""'}), "(default=None, description='User status, It is optional')\n", (1281, 1338), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((1362, 1432), 'fastapi.Query', 'Query', ([], {'default': '""""""', 'description': '"""String compare with name or last name"""'}), "(default='', description='String compare with name or last name')\n", (1367, 1432), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((1455, 1464), 'fastapi.Depends', 'Depends', ([], {}), '()\n', (1462, 1464), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((1497, 1517), 'fastapi.Depends', 'Depends', (['deps.get_db'], {}), '(deps.get_db)\n', (1504, 1517), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((2211, 2220), 'fastapi.Depends', 'Depends', ([], {}), '()\n', (2218, 2220), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((2253, 2273), 'fastapi.Depends', 'Depends', (['deps.get_db'], {}), '(deps.get_db)\n', (2260, 2273), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((2749, 2769), 'fastapi.Depends', 'Depends', (['deps.get_db'], {}), '(deps.get_db)\n', (2756, 2769), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((3358, 3378), 'fastapi.Depends', 'Depends', (['deps.get_db'], {}), '(deps.get_db)\n', (3365, 3378), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((3940, 3960), 'fastapi.Depends', 'Depends', (['deps.get_db'], {}), '(deps.get_db)\n', (3947, 3960), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((845, 919), 'app.api.deps.get_current_user', 'deps.get_current_user', ([], {'required_roles': '[IRoleEnum.admin, IRoleEnum.manager]'}), '(required_roles=[IRoleEnum.admin, IRoleEnum.manager])\n', (866, 919), False, 'from app.api import deps\n'), ((983, 1039), 'app.crud.user.get_multi_paginated', 'crud.user.get_multi_paginated', (['db_session'], {'params': 'params'}), '(db_session, params=params)\n', (1012, 1039), False, 'from app import crud\n'), ((1552, 1607), 'app.api.deps.get_current_user', 'deps.get_current_user', ([], {'required_roles': '[IRoleEnum.admin]'}), '(required_roles=[IRoleEnum.admin])\n', (1573, 1607), False, 'from app.api import deps\n'), ((1900, 1969), 'app.crud.user.get_multi_paginated', 'crud.user.get_multi_paginated', (['db_session'], {'query': 'query', 'params': 'params'}), '(db_session, query=query, params=params)\n', (1929, 1969), False, 'from app import crud\n'), ((2308, 2382), 'app.api.deps.get_current_user', 'deps.get_current_user', ([], {'required_roles': '[IRoleEnum.admin, IRoleEnum.manager]'}), '(required_roles=[IRoleEnum.admin, IRoleEnum.manager])\n', (2329, 2382), False, 'from app.api import deps\n'), ((2457, 2526), 'app.crud.user.get_multi_paginated', 'crud.user.get_multi_paginated', (['db_session'], {'query': 'query', 'params': 'params'}), '(db_session, query=query, params=params)\n', (2486, 2526), False, 'from app import crud\n'), ((2804, 2878), 'app.api.deps.get_current_user', 'deps.get_current_user', ([], {'required_roles': '[IRoleEnum.admin, IRoleEnum.manager]'}), '(required_roles=[IRoleEnum.admin, IRoleEnum.manager])\n', (2825, 2878), False, 'from app.api import deps\n'), ((2901, 2949), 'app.crud.user.get_user_by_id', 'crud.user.get_user_by_id', (['db_session'], {'id': 'user_id'}), '(db_session, id=user_id)\n', (2925, 2949), False, 'from app import crud\n'), ((3122, 3145), 'app.api.deps.get_current_user', 'deps.get_current_user', ([], {}), '()\n', (3143, 3145), False, 'from app.api import deps\n'), ((3413, 3468), 'app.api.deps.get_current_user', 'deps.get_current_user', ([], {'required_roles': '[IRoleEnum.admin]'}), '(required_roles=[IRoleEnum.admin])\n', (3434, 3468), False, 'from app.api import deps\n'), ((3495, 3551), 'app.crud.user.get_by_email', 'crud.user.get_by_email', (['db_session'], {'email': 'new_user.email'}), '(db_session, email=new_user.email)\n', (3517, 3551), False, 'from app import crud\n'), ((3579, 3664), 'fastapi.HTTPException', 'HTTPException', ([], {'status_code': '(404)', 'detail': '"""There is already a user with same email"""'}), "(status_code=404, detail='There is already a user with same email'\n    )\n", (3592, 3664), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((3677, 3732), 'app.crud.user.create_with_role', 'crud.user.create_with_role', (['db_session'], {'obj_in': 'new_user'}), '(db_session, obj_in=new_user)\n', (3703, 3732), False, 'from app import crud\n'), ((3995, 4050), 'app.api.deps.get_current_user', 'deps.get_current_user', ([], {'required_roles': '[IRoleEnum.admin]'}), '(required_roles=[IRoleEnum.admin])\n', (4016, 4050), False, 'from app.api import deps\n'), ((4105, 4177), 'fastapi.HTTPException', 'HTTPException', ([], {'status_code': '(404)', 'detail': '"""Users can not delete theirselfs"""'}), "(status_code=404, detail='Users can not delete theirselfs')\n", (4118, 4177), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((4196, 4255), 'app.crud.user.get_user_by_id', 'crud.user.get_user_by_id', ([], {'db_session': 'db_session', 'id': 'user_id'}), '(db_session=db_session, id=user_id)\n', (4220, 4255), False, 'from app import crud\n'), ((4287, 4341), 'fastapi.HTTPException', 'HTTPException', ([], {'status_code': '(404)', 'detail': '"""User no found"""'}), "(status_code=404, detail='User no found')\n", (4300, 4341), False, 'from fastapi import APIRouter, Depends, HTTPException, Query\n'), ((4363, 4403), 'app.crud.user.remove', 'crud.user.remove', (['db_session'], {'id': 'user_id'}), '(db_session, id=user_id)\n', (4379, 4403), False, 'from app import crud\n'), ((2400, 2412), 'sqlmodel.select', 'select', (['User'], {}), '(User)\n', (2406, 2412), False, 'from sqlmodel import select, and_\n'), ((1795, 1854), 'sqlmodel.and_', 'and_', (['(Role.name == role_name)', '(User.is_active == user_status)'], {}), '(Role.name == role_name, User.is_active == user_status)\n', (1799, 1854), False, 'from sqlmodel import select, and_\n'), ((1740, 1752), 'sqlmodel.select', 'select', (['User'], {}), '(User)\n', (1746, 1752), False, 'from sqlmodel import select, and_\n')]