"""
Admin-only endpoints. All routes in this router are protected by
`require_admin` (router-level dependency). Non-admin requests get 403.

See app/core/security.py for the require_admin implementation.
"""
import logging

from fastapi import APIRouter, Depends, HTTPException, status

from app.core.security import require_admin, CurrentUser
from app.schemas.admin import AdminUsersResponse, AdminStatsResponse, OrphanCvsResponse
from app.schemas.auth import MeResponse
from app.schemas.cv import CVPayloadInput, CVResponse
from app.schemas.profile import UpdateProfileRequest
from app.services import admin_service, auth_service, cv_service, profile_service
from app.services.cv_service import build_cv_response

logger = logging.getLogger(__name__)

router = APIRouter(
    prefix="/admin",
    tags=["admin"],
    dependencies=[Depends(require_admin)],
)


@router.get("/users", response_model=AdminUsersResponse)
def list_users(
    current_user: CurrentUser = Depends(require_admin),
) -> AdminUsersResponse:
    """
    List all candidate users in the system. Admin only.

    Returns merged profile + auth + cv data for every non-admin user (admins
    are excluded from this list). No pagination.
    """
    logger.info("GET /admin/users — admin=%s", current_user.user_id)
    return admin_service.list_all_users()


@router.get("/users/{user_id}/cv", response_model=CVResponse)
def get_user_cv(
    user_id: str,
    current_user: CurrentUser = Depends(require_admin),
) -> CVResponse:
    """
    Fetch a specific user's CV (admin perspective). Returns 404 if the user
    has no CV row. Reuses the same build_cv_response helper as GET /cvs/me
    to guarantee identical response shape and signed URL freshness.

    Note: we do NOT verify the user_id exists in profiles before fetching the CV.
    If the user_id is unknown, fetch_cv_by_user simply returns None -> 404, which
    is the desired behavior (admin sees "no CV" for invalid id, no info leak).
    """
    logger.info(
        "GET /admin/users/%s/cv — admin=%s",
        user_id,
        current_user.user_id,
    )

    response = build_cv_response(user_id)
    if response is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Aucun CV trouvé pour cet utilisateur.",
        )

    return response


@router.patch("/users/{user_id}/cv", response_model=CVResponse)
async def update_user_cv(
    user_id: str,
    payload: CVPayloadInput,
    current_user: CurrentUser = Depends(require_admin),
) -> CVResponse:
    """
    Create or update a specific user's CV (admin perspective) and regenerate
    its PDF. Reuses the same save_cv_for_user helper as POST /cvs/me to
    guarantee identical validation, best-effort PDF/storage behavior, and
    response shape.

    Note: no separate "user_id exists" check here — save_cv_for_user's own
    profile fetch already raises 404 if the target user has no profile row.
    """
    logger.info(
        "PATCH /admin/users/%s/cv — admin=%s",
        user_id,
        current_user.user_id,
    )
    return await cv_service.save_cv_for_user(user_id, payload)


@router.patch("/users/{user_id}/profile", response_model=MeResponse)
def update_user_profile(
    user_id: str,
    payload: UpdateProfileRequest,
    current_user: CurrentUser = Depends(require_admin),
) -> MeResponse:
    """
    Update a specific user's profile fields (admin perspective). Reuses
    profile_service.update_profile — same helper as PUT /profiles/me.

    Response is intentionally lightweight (no has_cv/created_at, which
    never change via this route).
    """
    logger.info(
        "PATCH /admin/users/%s/profile — admin=%s",
        user_id,
        current_user.user_id,
    )
    fields = payload.model_dump(exclude_unset=True, by_alias=False)
    try:
        result = profile_service.update_profile(user_id=user_id, fields=fields)
    except auth_service.ProfileNotFound:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Profil introuvable.",
        )
    except profile_service.ProfileUpdateError as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to update profile: {e}",
        )
    except auth_service.SupabaseAuthError as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to fetch user info after update: {e}",
        )

    return MeResponse(
        user_id=result.user_id,
        email=result.email,
        role=result.role,
        firstname=result.firstname,
        lastname=result.lastname,
        phone=result.phone,
        profession=result.profession,
        city=result.city,
    )


@router.get("/stats", response_model=AdminStatsResponse)
def get_stats(
    current_user: CurrentUser = Depends(require_admin),
) -> AdminStatsResponse:
    """
    Global counts for the admin dashboard KPI cards.
    """
    logger.info("GET /admin/stats — admin=%s", current_user.user_id)
    return admin_service.get_stats()


@router.delete("/users/{user_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_user(
    user_id: str,
    delete_cv: bool = False,
    current_user: CurrentUser = Depends(require_admin),
) -> None:
    """
    Delete a user account. Admin only. Admins cannot delete their own account.

    delete_cv=False (default): DB-level constraints handle cleanup — see
    admin_service.delete_user for the cascade/orphan behavior (profiles
    cascades, cvs.user_id set to NULL).

    delete_cv=True: additionally deletes the CV row and its storage files
    (cv.pdf + step audio recordings) — full, irreversible cleanup.
    """
    logger.info(
        "DELETE /admin/users/%s?delete_cv=%s — admin=%s",
        user_id, delete_cv, current_user.user_id,
    )
    try:
        admin_service.delete_user(user_id, current_user.user_id, delete_cv=delete_cv)
    except ValueError as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e),
        )
    except Exception as e:
        logger.exception("DELETE /admin/users/%s failed: %s", user_id, e)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to delete user.",
        )
    return None


@router.delete("/users/{user_id}/cv", status_code=status.HTTP_204_NO_CONTENT)
def delete_user_cv(
    user_id: str,
    current_user: CurrentUser = Depends(require_admin),
) -> None:
    """
    Delete a user's CV (storage files + row) while keeping their account
    intact. Admin only.
    """
    logger.info(
        "DELETE /admin/users/%s/cv — admin=%s",
        user_id, current_user.user_id,
    )
    try:
        admin_service.delete_user_cv_only(user_id)
    except Exception as e:
        logger.exception("DELETE /admin/users/%s/cv failed: %s", user_id, e)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to delete CV.",
        )
    return None


@router.get("/cvs/orphans", response_model=OrphanCvsResponse)
def list_orphan_cvs(
    current_user: CurrentUser = Depends(require_admin),
) -> OrphanCvsResponse:
    """
    List CV rows whose owning user has been deleted (user_id IS NULL).
    Feeds the future "Candidats / CV orphelins" toggle in UsersTab.
    """
    logger.info("GET /admin/cvs/orphans — admin=%s", current_user.user_id)
    return admin_service.list_orphan_cvs()


@router.delete("/cvs/orphans/{cv_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_orphan_cv(
    cv_id: str,
    current_user: CurrentUser = Depends(require_admin),
) -> None:
    """
    Delete an orphaned CV row (cvs.user_id IS NULL) and its storage files.
    Admin only.
    """
    logger.info(
        "DELETE /admin/cvs/orphans/%s — admin=%s",
        cv_id, current_user.user_id,
    )
    try:
        admin_service.delete_orphan_cv(cv_id)
    except Exception as e:
        logger.exception("DELETE /admin/cvs/orphans/%s failed: %s", cv_id, e)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to delete orphan CV.",
        )
    return None
