from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
from sqlalchemy.orm import Session

from app.database import SessionLocal, get_db, release_db_connection
from app.dependencies import require_user_token
from app.models import User
from app.schemas import ChangePasswordRequest, Message, ProfileUpdate, UserPublic
from app.security import hash_password, verify_password
from app.services.user_profile_service import serialize_user_public, update_user_profile
from app.services.user_profile_image_service import save_user_profile_image, set_user_profile_image

router = APIRouter(prefix="/profile", tags=["user-profile"])


def _load_user_public(db: Session, user_id: int) -> UserPublic:
    u = db.query(User).filter(User.id == user_id).first()
    assert u is not None
    return serialize_user_public(u, db)


@router.get("", response_model=UserPublic)
def get_profile(db: Session = Depends(get_db), me: User = Depends(require_user_token)):
    return _load_user_public(db, me.id)


@router.patch("/update", response_model=UserPublic)
def update_profile(
    body: ProfileUpdate,
    db: Session = Depends(get_db),
    me: User = Depends(require_user_token),
):
    """
    Update the logged-in user's profile.

    Requires `Authorization: Bearer <token>` from login.
    """
    if body.email and str(body.email) != me.email:
        exists = db.query(User).filter(User.email == body.email, User.id != me.id).first()
        if exists:
            raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Email already in use")

    try:
        update_user_profile(db, me, body)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) from e

    return _load_user_public(db, me.id)


@router.patch("", response_model=UserPublic, include_in_schema=False)
def update_profile_legacy(
    body: ProfileUpdate,
    db: Session = Depends(get_db),
    me: User = Depends(require_user_token),
):
    """Alias for PATCH /profile/update."""
    return update_profile(body, db, me)


@router.post("/upload-image", response_model=UserPublic, summary="Upload user profile image")
async def upload_profile_image(
    db: Session = Depends(get_db),
    me: User = Depends(require_user_token),
    image: UploadFile = File(..., description="Profile image (jpg, png, gif, webp)"),
):
    if not image.filename:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Image file is required")
    user_id = me.id
    release_db_connection(db)
    image_path = await save_user_profile_image(image)
    write_db = SessionLocal()
    try:
        user = write_db.get(User, user_id)
        if user is None:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User not found")
        user = set_user_profile_image(write_db, user, image_path)
        return serialize_user_public(user, write_db)
    finally:
        write_db.close()


@router.post("/change-password", response_model=Message, summary="Change logged-in user password")
def change_password(
    body: ChangePasswordRequest,
    db: Session = Depends(get_db),
    me: User = Depends(require_user_token),
):
    if not verify_password(body.current_password, me.hashed_password):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Current password is incorrect",
        )
    if body.current_password == body.new_password:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="New password must be different from current password",
        )
    me.hashed_password = hash_password(body.new_password)
    db.commit()
    return Message(message="Password updated successfully")
