from __future__ import annotations

from fastapi import APIRouter, Depends, File, HTTPException, Request, UploadFile

from ...core.logger import AppLogger
from ...core.permissions import PERMISSION_USER_CREATE, PERMISSION_USER_LIST
from ...database.orm import UserORM
from ...services import AuthService, OperationLogService
from ..dependencies import get_auth_service, get_current_user, get_operation_log_service, require_permission
from ..request_meta import operation_request_meta
from ..schemas.auth import (
    ChangePasswordRequest,
    ChangePasswordResponse,
    CreateUserRequest,
    LoginRequest,
    LoginResponse,
    UpdateProfileRequest,
    UserProfileDTO,
    UserResponse,
)

router = APIRouter(prefix="/api/auth", tags=["auth"])
logger = AppLogger.get_logger(__name__)


@router.post("/login", response_model=LoginResponse)
def login(
    http_request: Request,
    request: LoginRequest,
    service: AuthService = Depends(get_auth_service),
    operation_logs: OperationLogService = Depends(get_operation_log_service),
) -> LoginResponse:
    """登录成功后返回 token、可见菜单和可执行操作权限。"""
    try:
        session = service.login(request.username, request.password)
    except ValueError as exc:
        operation_logs.record(
            actor=None,
            module="auth",
            action="login",
            target_type="user",
            target_id=request.username,
            status="failed",
            detail=str(exc),
            **operation_request_meta(http_request),
        )
        logger.error("登录接口失败 username=%s reason=%s", request.username, exc)
        raise HTTPException(status_code=401, detail=str(exc)) from exc
    operation_logs.record(
        actor=session.user,
        module="auth",
        action="login",
        target_type="user",
        target_id=str(session.user.id),
        status="success",
        detail="用户登录成功",
        **operation_request_meta(http_request),
    )
    return LoginResponse.from_session(session)


@router.get("/me", response_model=UserProfileDTO)
def me(current_user: UserORM = Depends(get_current_user)) -> UserProfileDTO:
    """前端刷新页面时用它恢复当前用户权限上下文。"""
    return UserProfileDTO.from_orm_model(current_user)


@router.put("/me", response_model=UserProfileDTO)
def update_me(
    http_request: Request,
    request: UpdateProfileRequest,
    current_user: UserORM = Depends(get_current_user),
    service: AuthService = Depends(get_auth_service),
    operation_logs: OperationLogService = Depends(get_operation_log_service),
) -> UserProfileDTO:
    """当前登录用户修改个人基础信息。"""
    try:
        user = service.update_profile(
            current_user.id,
            display_name=request.display_name,
            email=request.email,
            phone=request.phone,
            department=request.department,
            position_title=request.position_title,
        )
    except ValueError as exc:
        operation_logs.record(
            actor=current_user,
            module="auth",
            action="profile.update",
            target_type="user",
            target_id=str(current_user.id),
            status="failed",
            detail=str(exc),
            **operation_request_meta(http_request),
        )
        logger.error("修改个人资料接口失败 user_id=%s reason=%s", current_user.id, exc)
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    operation_logs.record(
        actor=user,
        module="auth",
        action="profile.update",
        target_type="user",
        target_id=str(user.id),
        status="success",
        detail="修改个人资料成功",
        **operation_request_meta(http_request),
    )
    return UserProfileDTO.from_orm_model(user)


@router.put("/me/password", response_model=ChangePasswordResponse)
def change_my_password(
    http_request: Request,
    request: ChangePasswordRequest,
    current_user: UserORM = Depends(get_current_user),
    service: AuthService = Depends(get_auth_service),
    operation_logs: OperationLogService = Depends(get_operation_log_service),
) -> ChangePasswordResponse:
    """当前登录用户修改自己的登录密码。"""
    try:
        service.change_password(
            current_user.id,
            old_password=request.old_password,
            new_password=request.new_password,
            confirm_password=request.confirm_password,
        )
    except ValueError as exc:
        operation_logs.record(
            actor=current_user,
            module="auth",
            action="password.change",
            target_type="user",
            target_id=str(current_user.id),
            status="failed",
            detail=str(exc),
            **operation_request_meta(http_request),
        )
        logger.error("修改密码接口失败 user_id=%s reason=%s", current_user.id, exc)
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    operation_logs.record(
        actor=current_user,
        module="auth",
        action="password.change",
        target_type="user",
        target_id=str(current_user.id),
        status="success",
        detail="修改密码成功",
        **operation_request_meta(http_request),
    )
    return ChangePasswordResponse(message="密码修改成功")


@router.post("/me/avatar", response_model=UserProfileDTO)
def update_my_avatar(
    http_request: Request,
    file: UploadFile = File(...),
    current_user: UserORM = Depends(get_current_user),
    service: AuthService = Depends(get_auth_service),
    operation_logs: OperationLogService = Depends(get_operation_log_service),
) -> UserProfileDTO:
    """当前登录用户上传并修改头像。"""
    try:
        user = service.update_avatar(
            current_user.id,
            filename=file.filename or "avatar.png",
            stream=file.file,
        )
    except ValueError as exc:
        operation_logs.record(
            actor=current_user,
            module="auth",
            action="avatar.update",
            target_type="user",
            target_id=str(current_user.id),
            status="failed",
            detail=str(exc),
            **operation_request_meta(http_request),
        )
        logger.error("修改头像接口失败 user_id=%s filename=%s reason=%s", current_user.id, file.filename, exc)
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    operation_logs.record(
        actor=user,
        module="auth",
        action="avatar.update",
        target_type="user",
        target_id=str(user.id),
        status="success",
        detail=f"修改头像成功 filename={file.filename or 'avatar.png'}",
        **operation_request_meta(http_request),
    )
    return UserProfileDTO.from_orm_model(user)


@router.post(
    "/users",
    response_model=UserResponse,
)
def create_user(
    http_request: Request,
    request: CreateUserRequest,
    current_user: UserORM = Depends(require_permission(PERMISSION_USER_CREATE)),
    service: AuthService = Depends(get_auth_service),
    operation_logs: OperationLogService = Depends(get_operation_log_service),
) -> UserResponse:
    """只有超级用户可以创建用户，角色决定菜单和操作权限。"""
    try:
        user = service.create_user(
            username=request.username,
            password=request.password,
            role=request.role,
            display_name=request.display_name,
            email=request.email,
            phone=request.phone,
            department=request.department,
            position_title=request.position_title,
        )
    except ValueError as exc:
        operation_logs.record(
            actor=current_user,
            module="system",
            action="user.create",
            target_type="user",
            target_id=request.username,
            status="failed",
            detail=str(exc),
            **operation_request_meta(http_request),
        )
        logger.error("创建用户接口失败 username=%s role=%s reason=%s", request.username, request.role, exc)
        raise HTTPException(status_code=400, detail=str(exc)) from exc
    operation_logs.record(
        actor=current_user,
        module="system",
        action="user.create",
        target_type="user",
        target_id=str(user.id),
        status="success",
        detail=f"创建用户成功 username={user.username} role={user.role}",
        **operation_request_meta(http_request),
    )
    return UserResponse.from_orm_model(user)


@router.get(
    "/users",
    response_model=list[UserResponse],
)
def list_users(
    http_request: Request,
    current_user: UserORM = Depends(require_permission(PERMISSION_USER_LIST)),
    service: AuthService = Depends(get_auth_service),
    operation_logs: OperationLogService = Depends(get_operation_log_service),
) -> list[UserResponse]:
    """用户管理菜单使用的用户列表。"""
    users = service.list_users()
    operation_logs.record(
        actor=current_user,
        module="system",
        action="user.list",
        target_type="user",
        target_id="",
        status="success",
        detail=f"查询用户列表 count={len(users)}",
        **operation_request_meta(http_request),
    )
    return [UserResponse.from_orm_model(user) for user in users]
