"""User management endpoints - admin only."""

from __future__ import annotations

from typing import Annotated

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

from src.web.api.auth import get_current_user
from src.web.db.session import get_db
from src.web.db.models import User
from src.web.schemas.users import (
    UserCreateRequest,
    UserResponse,
    UserUpdateRequest,
    UsersListResponse,
)
from src.web.utils.password import hash_password

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


def get_current_admin_user(
    current_user: Annotated[dict, Depends(get_current_user)],
    db: Session = Depends(get_db),
) -> dict:
    """Get current user and verify admin status from main database.
    
    Raises HTTPException if user is not an admin.
    If no admin users exist, allows the current user to bootstrap as admin.
    """
    username = current_user["username"]
    
    # Check if any admin users exist
    admin_count = db.query(User).filter(User.is_admin == True).count()
    
    # If no admins exist, allow current user to bootstrap as admin
    if admin_count == 0:
        # Check if user already exists in main database
        main_user = db.query(User).filter(User.username == username).first()
        if not main_user:
            # Create the user as admin for bootstrap
            # Use a default password hash (user should change password after first login)
            # In production, this should be handled differently
            default_password_hash = hash_password("changeme")
            main_user = User(
                username=username,
                password_hash=default_password_hash,
                is_active=True,
                is_admin=True,
            )
            db.add(main_user)
            db.commit()
            db.refresh(main_user)
        elif not main_user.is_admin:
            # User exists but is not admin - make them admin for bootstrap
            main_user.is_admin = True
            db.add(main_user)
            db.commit()
            db.refresh(main_user)
        
        return {"username": username, "user_id": main_user.id}
    
    # Normal admin check - user must exist and be admin
    main_user = db.query(User).filter(User.username == username).first()
    
    if not main_user or not main_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Admin access required",
        )
    
    return {"username": username, "user_id": main_user.id}


@router.get("", response_model=UsersListResponse)
def list_users(
    current_admin: Annotated[dict, Depends(get_current_admin_user)],
    is_active: bool | None = Query(None, description="Filter by active status"),
    is_admin: bool | None = Query(None, description="Filter by admin status"),
    db: Session = Depends(get_db),
) -> UsersListResponse:
    """List all users - admin only.
    
    Optionally filter by is_active and/or is_admin status.
    """
    query = db.query(User)
    
    if is_active is not None:
        query = query.filter(User.is_active == is_active)
    
    if is_admin is not None:
        query = query.filter(User.is_admin == is_admin)
    
    users = query.order_by(User.username.asc()).all()
    items = [UserResponse.model_validate(u) for u in users]
    return UsersListResponse(items=items, total=len(items))


@router.post("", response_model=UserResponse, status_code=status.HTTP_201_CREATED)
def create_user(
    current_admin: Annotated[dict, Depends(get_current_admin_user)],
    request: UserCreateRequest,
    db: Session = Depends(get_db),
) -> UserResponse:
    """Create a new user - admin only."""
    # Check if username already exists
    existing_user = db.query(User).filter(User.username == request.username).first()
    if existing_user:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Username '{request.username}' already exists",
        )
    
    # Hash the password before storing
    password_hash = hash_password(request.password)
    
    user = User(
        username=request.username,
        password_hash=password_hash,
        email=request.email,
        full_name=request.full_name,
        is_active=request.is_active,
        is_admin=request.is_admin,
        password_change_required=True,  # Force password change on first login
    )
    db.add(user)
    db.commit()
    db.refresh(user)
    
    return UserResponse.model_validate(user)


@router.get("/{user_id}", response_model=UserResponse)
def get_user(
    current_admin: Annotated[dict, Depends(get_current_admin_user)],
    user_id: int,
    db: Session = Depends(get_db),
) -> UserResponse:
    """Get a specific user by ID - admin only."""
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"User with ID {user_id} not found",
        )
    return UserResponse.model_validate(user)


@router.put("/{user_id}", response_model=UserResponse)
def update_user(
    current_admin: Annotated[dict, Depends(get_current_admin_user)],
    user_id: int,
    request: UserUpdateRequest,
    db: Session = Depends(get_db),
) -> UserResponse:
    """Update a user - admin only."""
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"User with ID {user_id} not found",
        )
    
    # Prevent admin from removing their own admin status
    if (
        current_admin["username"] == user.username
        and request.is_admin is not None
        and not request.is_admin
    ):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Cannot remove your own admin status",
        )
    
    # Update fields if provided
    if request.password is not None:
        user.password_hash = hash_password(request.password)
    if request.email is not None:
        user.email = request.email
    if request.full_name is not None:
        user.full_name = request.full_name
    if request.is_active is not None:
        user.is_active = request.is_active
    if request.is_admin is not None:
        user.is_admin = request.is_admin
    
    db.add(user)
    db.commit()
    db.refresh(user)
    
    return UserResponse.model_validate(user)


@router.delete("/{user_id}")
def delete_user(
    current_admin: Annotated[dict, Depends(get_current_admin_user)],
    user_id: int,
    db: Session = Depends(get_db),
) -> Response:
    """Delete a user - admin only.
    
    Prevents admin from deleting themselves.
    """
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"User with ID {user_id} not found",
        )
    
    # Prevent admin from deleting themselves
    if current_admin["username"] == user.username:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Cannot delete your own account",
        )
    
    db.delete(user)
    db.commit()
    
    return Response(status_code=status.HTTP_204_NO_CONTENT)

