from pathlib import Path
import uuid
from datetime import datetime
from fastapi import HTTPException, UploadFile, status
from sqlmodel import Session

from app.models.user import User, Role
from app.schemas.user import UserUpdate
from app.repositories.user_repo import UserRepository
from app.core.security import hash_password, verify_password
from app.utils.image import validate_profile_image
from app.core.config import get_settings
from app.core.constants import ERR_FORBIDDEN, ERR_OLD_PASSWORD, ERR_ADMINS_CAN_DELETE_ONLY_STANDARD_USERS

settings = get_settings()

class UserService:
    """Service for user-specific operations."""

    @staticmethod
    def update_user(current_user: User, data: UserUpdate, session: Session) -> User:
        """Update profile fields on the current user."""
        for field, value in data.model_dump(exclude_unset=True).items():
            setattr(current_user, field, value)
        current_user.updated_at = datetime.utcnow()
        return UserRepository.update(session, current_user)

    @staticmethod
    def update_profile_image(current_user: User, file: UploadFile, session: Session) -> User:
        """Validate and store profile image, update user's profile_image field."""
        validate_profile_image(file)
        # Use pathlib for handling paths
        profile_image_directory = Path(settings.PROFILE_IMAGE_DIRECTORY)
        # Ensure the directory exists
        profile_image_directory.mkdir(parents=True, exist_ok=True)
        # Create a unique name for the profile image
        unique_name = f"{uuid.uuid4().hex}_{file.filename}"
        # Define the full file path
        file_path = profile_image_directory / unique_name
        # Save the file to the defined path
        with open(file_path, "wb") as buffer:
            buffer.write(file.file.read())
        # Update the user's profile image and last update time
        current_user.profile_image = str(file_path)
        current_user.updated_at = datetime.utcnow()
        # Save the user with the updated profile image
        return UserRepository.update(session, current_user)

    @staticmethod
    def change_password(current_user: User, old_password: str, new_password: str, session: Session) -> User:
        """Change password after validating the old password."""
        if not verify_password(old_password, current_user.hashed_password):
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=ERR_OLD_PASSWORD)
        current_user.hashed_password = hash_password(new_password)
        current_user.refresh_token = None
        current_user.updated_at = datetime.utcnow()
        return UserRepository.update(session, current_user)

    @staticmethod
    def delete_user(current_user: User, target: User, session: Session) -> None:
        """Soft-delete a target user respecting role-based rules."""
        if current_user.role == Role.USERS:
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERR_FORBIDDEN)
        if current_user.role == Role.ADMIN and target.role != Role.USERS:
            raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERR_ADMINS_CAN_DELETE_ONLY_STANDARD_USERS)
        return UserRepository.soft_delete_user(session, target)
