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

from app.core.dependencies import get_current_user
from app.core.media_signing import build_signed_media_url
from app.core.redis import check_rate_limit
from app.modules.media.service import AvatarValidationError
from app.modules.users.schemas import PasswordChangeIn, UserPatchIn
from app.modules.users.service import change_password, get_me, update_me, upload_avatar

router = APIRouter()


def _profile_response(data: dict) -> dict:
    return {
        "user": {
            "id": data["user"].id,
            "email": data["user"].email,
            "role": data["user"].role,
            "status": data["user"].status,
        },
        "profile": {
            "display_name": data["profile"].display_name,
            "avatar_url": build_signed_media_url(data["profile"].avatar_url),
        },
    }


@router.get("/me")
async def me_route(current_user=Depends(get_current_user)):
    return _profile_response(get_me(current_user))


@router.patch("/me")
async def patch_me_route(payload: UserPatchIn, current_user=Depends(get_current_user)):
    return _profile_response(update_me(current_user, payload.display_name))


@router.post("/me/password")
async def change_password_route(payload: PasswordChangeIn, current_user=Depends(get_current_user)):
    try:
        change_password(current_user, payload.current_password, payload.new_password)
    except ValueError:
        raise HTTPException(status_code=400, detail="INVALID_CURRENT_PASSWORD")
    return {"message": "password_changed"}


@router.post("/me/avatar")
async def upload_avatar_route(
    request: Request,
    file: UploadFile = File(...),
    current_user=Depends(get_current_user),
):
    check_rate_limit(f"avatar:{current_user.id}", limit=10, window_seconds=3600)
    content = await file.read()
    try:
        data = upload_avatar(current_user, content)
    except AvatarValidationError as exc:
        raise HTTPException(status_code=400, detail=str(exc))
    return _profile_response(data)
