from __future__ import annotations
from typing import Annotated

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session

from app.api.deps import get_current_user, require_roles
from app.core.i18n import Language, get_language, translate
from app.core.security import get_password_hash
from app.db.session import get_db
from app.models.enums import Role
from app.models.user import User
from app.schemas.user import FUNCTIONALITY_KEYS, UserCreate, UserRead, UserUpdate

router = APIRouter(dependencies=[Depends(require_roles(Role.admin))])


@router.get("", response_model=list[UserRead])
def list_users(db: Annotated[Session, Depends(get_db)]):
    return db.query(User).order_by(User.username).all()


@router.post("", response_model=UserRead)
def create_user(
    payload: UserCreate,
    db: Annotated[Session, Depends(get_db)],
    language: Annotated[Language, Depends(get_language)],
):
    if payload.functionality_access is not None and not set(payload.functionality_access).issubset(FUNCTIONALITY_KEYS):
        raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Unknown functionality access")
    if db.query(User).filter(User.username == payload.username).first():
        raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=translate("users.username_exists", language))
    user = User(
        username=payload.username,
        full_name=payload.full_name,
        email=payload.email,
        role=payload.role,
        is_active=payload.is_active,
        functionality_access=payload.functionality_access,
        hashed_password=get_password_hash(payload.password),
    )
    db.add(user)
    db.commit()
    db.refresh(user)
    return user


@router.put("/{user_id}", response_model=UserRead)
def update_user(
    user_id: int,
    payload: UserUpdate,
    db: Annotated[Session, Depends(get_db)],
    language: Annotated[Language, Depends(get_language)],
    current_admin: Annotated[User, Depends(get_current_user)],
):
    user = db.get(User, user_id)
    if not user:
        raise HTTPException(status_code=404, detail=translate("users.not_found", language))
    if user.id == current_admin.id:
        if payload.role is not None and payload.role != Role.admin:
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="You cannot remove your own admin role")
        if payload.is_active is False:
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="You cannot deactivate your own account")
    if payload.username and payload.username != user.username:
        if db.query(User).filter(User.username == payload.username).first():
            raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail=translate("users.username_exists", language))
    if payload.functionality_access is not None and not set(payload.functionality_access).issubset(FUNCTIONALITY_KEYS):
        raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail="Unknown functionality access")
    for key, value in payload.model_dump(exclude_unset=True, exclude={"password"}).items():
        setattr(user, key, value)
    if payload.password:
        user.hashed_password = get_password_hash(payload.password)
    db.commit()
    db.refresh(user)
    return user
