"""
User management endpoints.

CRUD operations for staff and lab users, activation/deactivation, and password changes.
"""

import asyncio
from uuid import UUID

from fastapi import APIRouter, Depends, Query, UploadFile, status
from fastapi.responses import Response
from sqlalchemy.ext.asyncio import AsyncSession

from app.core.auth_deps import get_current_active_user, require_permission
from app.core.dependencies import get_db
from app.core.exceptions import NotFoundException
from app.core.pagination import PaginationParams
from app.core.permissions import PermissionCode
from app.core.responses import PaginatedResponse, SuccessResponse
from app.models.user import User, UserRole
from app.schemas.user import (
    AdminPasswordResetRequest,
    ChangePasswordRequest,
    UserCreate,
    UserResponse,
    UserUpdate,
)
from app.services import signature_service
from app.services.user_service import UserService

router = APIRouter(prefix="/users", tags=["Users"])
_user_service = UserService()


@router.get(
    "",
    response_model=PaginatedResponse[UserResponse],
    status_code=status.HTTP_200_OK,
    summary="List users",
    description="Retrieve paginated list of staff members with optional filtering.",
    dependencies=[Depends(require_permission(PermissionCode.USER_READ))],
)
async def list_users(
    params: PaginationParams = Depends(),
    lab_id: UUID | None = Query(None, description="Filter by lab branch ID"),
    role: UserRole | None = Query(None, description="Filter by user role"),
    is_active: bool | None = Query(None, description="Filter by active status"),
    db: AsyncSession = Depends(get_db),
) -> PaginatedResponse[UserResponse]:
    return await _user_service.list_users(
        db,
        params,
        lab_id=lab_id,
        role=role,
        is_active=is_active,
    )


@router.post(
    "",
    response_model=SuccessResponse[UserResponse],
    status_code=status.HTTP_201_CREATED,
    summary="Create user",
    description="Register a new staff member or additional superadmin.",
)
async def create_user(
    payload: UserCreate,
    current_user: User = Depends(require_permission(PermissionCode.USER_WRITE)),
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[UserResponse]:
    user = await _user_service.create_user(db, payload, creator=current_user)
    return SuccessResponse(data=user)


@router.get(
    "/me",
    response_model=SuccessResponse[UserResponse],
    status_code=status.HTTP_200_OK,
    summary="Get own profile",
    description="Retrieve the current user's profile details.",
)
async def get_own_profile(
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[UserResponse]:
    user = await _user_service.get_user(db, current_user.id)
    return SuccessResponse(data=user)


@router.get(
    "/{user_id}",
    response_model=SuccessResponse[UserResponse],
    status_code=status.HTTP_200_OK,
    summary="Get user details",
    description="Retrieve profile details for a specific user.",
    dependencies=[Depends(require_permission(PermissionCode.USER_READ))],
)
async def get_user(
    user_id: UUID,
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[UserResponse]:
    user = await _user_service.get_user(db, user_id)
    return SuccessResponse(data=user)


@router.patch(
    "/{user_id}",
    response_model=SuccessResponse[UserResponse],
    status_code=status.HTTP_200_OK,
    summary="Update user",
    description="Update profile or role information for a user.",
)
async def update_user(
    user_id: UUID,
    payload: UserUpdate,
    current_user: User = Depends(require_permission(PermissionCode.USER_WRITE)),
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[UserResponse]:
    user = await _user_service.update_user(db, user_id, payload, actor=current_user)
    return SuccessResponse(data=user)


@router.delete(
    "/{user_id}",
    response_model=SuccessResponse[dict[str, str]],
    status_code=status.HTTP_200_OK,
    summary="Delete user",
    description="Soft delete or remove a user account.",
)
async def delete_user(
    user_id: UUID,
    current_user: User = Depends(require_permission(PermissionCode.USER_WRITE)),
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[dict[str, str]]:
    await _user_service.delete_user(db, user_id, actor=current_user)
    return SuccessResponse(data={"message": f"User '{user_id}' deleted successfully."})


@router.post(
    "/{user_id}/activate",
    response_model=SuccessResponse[UserResponse],
    status_code=status.HTTP_200_OK,
    summary="Activate user",
    description="Activate a user account to restore login access.",
)
async def activate_user(
    user_id: UUID,
    current_user: User = Depends(require_permission(PermissionCode.USER_WRITE)),
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[UserResponse]:
    user = await _user_service.activate_user(db, user_id, actor=current_user)
    return SuccessResponse(data=user)


@router.post(
    "/{user_id}/deactivate",
    response_model=SuccessResponse[UserResponse],
    status_code=status.HTTP_200_OK,
    summary="Deactivate user",
    description="Deactivate a user account to block login access.",
)
async def deactivate_user(
    user_id: UUID,
    current_user: User = Depends(require_permission(PermissionCode.USER_WRITE)),
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[UserResponse]:
    user = await _user_service.deactivate_user(db, user_id, actor=current_user)
    return SuccessResponse(data=user)


@router.post(
    "/{user_id}/reset-password",
    response_model=SuccessResponse[dict[str, str]],
    status_code=status.HTTP_200_OK,
    summary="Reset staff password",
    description="Superadmin-only: set a new password for any staff account.",
)
async def reset_staff_password(
    user_id: UUID,
    payload: AdminPasswordResetRequest,
    current_user: User = Depends(require_permission(PermissionCode.USER_WRITE)),
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[dict[str, str]]:
    await _user_service.reset_password(db, user_id, payload.password, actor=current_user)
    return SuccessResponse(data={"message": "Staff password reset successfully."})


@router.post(
    "/me/change-password",
    response_model=SuccessResponse[dict[str, str]],
    status_code=status.HTTP_200_OK,
    summary="Change password",
    description="Change the current user's password.",
)
async def change_password(
    payload: ChangePasswordRequest,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[dict[str, str]]:
    await _user_service.change_password(db, current_user, payload)
    return SuccessResponse(data={"message": "Password changed successfully."})


@router.post(
    "/me/signature",
    response_model=SuccessResponse[UserResponse],
    status_code=status.HTTP_200_OK,
    summary="Upload own signature",
    description="Upload a signature scan; white paper is made transparent server-side for PDF overlay.",
)
async def upload_own_signature(
    file: UploadFile,
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[UserResponse]:
    raw = await file.read(signature_service.MAX_SIGNATURE_BYTES + 1)
    relative = await asyncio.to_thread(
        signature_service.save_signature, current_user.id, raw, file.content_type
    )
    current_user.signature_image_path = relative
    await db.flush()
    await db.refresh(current_user)
    return SuccessResponse(
        data=UserResponse.model_validate(current_user),
        message="Signature uploaded successfully.",
    )


@router.get(
    "/me/signature",
    status_code=status.HTTP_200_OK,
    summary="Download own signature",
    description="Fetch the current user's transparent signature PNG for profile preview.",
    response_class=Response,
)
async def download_own_signature(
    current_user: User = Depends(get_current_active_user),
) -> Response:
    data = signature_service.read_signature_bytes(current_user.signature_image_path)
    if data is None:
        raise NotFoundException(message="No signature uploaded yet.")
    return Response(content=data, media_type="image/png")


@router.delete(
    "/me/signature",
    response_model=SuccessResponse[UserResponse],
    status_code=status.HTTP_200_OK,
    summary="Remove own signature",
    description="Delete the current user's stored signature image.",
)
async def delete_own_signature(
    current_user: User = Depends(get_current_active_user),
    db: AsyncSession = Depends(get_db),
) -> SuccessResponse[UserResponse]:
    signature_service.delete_signature(current_user.id)
    current_user.signature_image_path = None
    await db.flush()
    await db.refresh(current_user)
    return SuccessResponse(
        data=UserResponse.model_validate(current_user),
        message="Signature removed successfully.",
    )
