from app.services.merchant_services import ( generate_login_otp_service, login_service, refresh_token_service, logout_service, get_user_details_service, ) from fastapi.security import OAuth2PasswordRequestForm from fastapi import APIRouter, HTTPException, Query, Depends, status, Body from app.models.merchant import LoginOtpRequest, RefreshTokenRequest, MerchantDetailsResponse from app.utils.auth_utils import verify_token import logging # Initialize router and logger router = APIRouter(prefix="/merchant") logger = logging.getLogger(__name__) @router.post("/login/otp") async def generate_login_otp(payload: LoginOtpRequest): """ Generate and send login OTP to the provided email or mobile number. Args: payload (GenerateLoginOtpRequest): The request payload containing the identifier. Returns: dict: Confirmation message indicating OTP has been sent. """ try: result = await generate_login_otp_service(payload.identifier) return result except HTTPException as e: logger.error("Failed to generate login OTP: %s", e.detail) raise e except Exception as e: logger.error("Unexpected error while generating login OTP: %s", e) raise HTTPException(status_code=500, detail="Failed to generate login OTP") from e @router.post("/login") async def login(user: OAuth2PasswordRequestForm = Depends()): """ Login using email/mobile and OTP. Args: user (OAuth2PasswordRequestForm): Contains username (email/mobile) and password (OTP). Returns: dict: Access and refresh tokens. """ try: result = await login_service(user.username, user.password) return result except HTTPException as e: logger.error("Login failed: %s", e.detail) raise e except Exception as e: logger.error("Unexpected error during login: %s", e) raise HTTPException(status_code=500, detail="Login failed") from e @router.post("/token/refresh") async def refresh_token(payload: RefreshTokenRequest): """ Refresh access and refresh tokens. Args: payload (RefreshTokenRequest): The request payload containing the identifier and refresh token. Returns: dict: New access and refresh tokens. """ try: result = await refresh_token_service(payload.identifier, payload.refresh_token) return result except HTTPException as e: logger.error("Failed to refresh token for identifier %s: %s", payload.identifier, e.detail) raise e except Exception as e: logger.error("Unexpected error while refreshing token for identifier %s: %s", payload.identifier, e) raise HTTPException(status_code=500, detail="Failed to refresh token") from e @router.post("/logout") async def logout(payload: LoginOtpRequest): """ Logout the user by invalidating access and refresh tokens. Args: identifier (str): Email or mobile number. Returns: dict: Confirmation message. """ try: result = await logout_service(payload.identifier) return result except HTTPException as e: logger.error("Failed to logout: %s", e.detail) raise e except Exception as e: logger.error("Unexpected error during logout: %s", e) raise HTTPException(status_code=500, detail="Failed to logout") from e @router.get("/user/details", response_model=MerchantDetailsResponse, dependencies=[Depends(verify_token)]) async def get_user_details(identifier: str = Query(..., description="Email or Mobile number")): """ Get user details using the identifier (email or mobile). Args: identifier (str): Email or mobile number. Returns: MerchantDetailsResponse: User details from the database. """ try: result = await get_user_details_service(identifier) return result except HTTPException as e: logger.error("Failed to retrieve user details for identifier %s: %s", identifier, e.detail) raise e except Exception as e: logger.error("Unexpected error while retrieving user details for identifier %s: %s", identifier, e) raise HTTPException(status_code=500, detail="Failed to retrieve user details") from e