from typing import Annotated, List, Optional from api.router.user import user_dependency from fastapi import APIRouter, Depends from fastapi.responses import JSONResponse from db.models import User_Meta, Metadata, Category from db.database import get_db from sqlalchemy.orm import Session from sqlalchemy.exc import SQLAlchemyError router = APIRouter(tags=["Book_Collection"]) db_dependency = Annotated[Session, Depends(get_db)] @router.get("/book_collection") async def get_book_collection( user: user_dependency, db: db_dependency, ): """This function will return a BookCollection""" if user is None: return JSONResponse(status_code=401, content="Authentication Failed") try: # Fetch all User_Meta entries for the user and their associated Metadata user_meta_entries = ( db.query(User_Meta, Metadata, Category) # Select User_Meta, Metadata, and Category .join(Metadata, Metadata.id == User_Meta.metadata_id) # Join on metadata_id .join(Category, Category.id == Metadata.category_id) # Join on category_id .filter(User_Meta.user_id == user.get("id")) .all() ) if not user_meta_entries: return {"info": "No book collection found"} # Extract relevant data from the user_meta_entries results = [ { "user_id": user_meta.user_id, "metadata_id": metadata.id, # Access Metadata fields "title": metadata.title, # Replace with actual field names in Metadata "author": metadata.author, # Replace with actual field names in Metadata "category_name": category.category, # Replace with actual field names in Category "year": metadata.year, "publisher": metadata.publisher # Add other Metadata and Category fields as needed } for user_meta, metadata, category in user_meta_entries # Unpack the tuple ] return { "status": "success", "book_collection": results, # Return the list of metadata } except SQLAlchemyError as e: return JSONResponse(status_code=500, content=f"Database error: {str(e)}") except Exception as e: return JSONResponse( status_code=500, content=f"An unexpected error occurred: {str(e)}" ) @router.post("/book_collection") async def request_book_collection( user: user_dependency, db: db_dependency, metadata_id: List[Optional[int]], ): if user is None: return JSONResponse(status_code=401, content="Authentication Failed") try: # Create User_Meta instances for each metadata_id user_meta_entries = [ User_Meta(user_id=user.get("id"), metadata_id=mid) for mid in metadata_id ] # Insert all entries into the database db.add_all(user_meta_entries) db.commit() # Commit the transaction except SQLAlchemyError as e: return JSONResponse(status_code=500, content=f"Database error: {str(e)}") except Exception as e: return JSONResponse( status_code=500, content=f"An unexpected error occurred: {str(e)}" ) return {"status": "success", "user_meta": [entry.id for entry in user_meta_entries]} @router.put("/book_collection") async def update_book_collection( user: user_dependency, db: db_dependency, metadata_id: List[Optional[int]], # Use the Pydantic model ): if user is None: return JSONResponse(status_code=401, content="Authentication Failed") try: # Fetch and delete existing User_Meta entries db.query(User_Meta).filter(User_Meta.user_id == user.get("id")).delete( synchronize_session=False ) db.commit() # Insert new User_Meta entries user_meta_entries = [ User_Meta(user_id=user.get("id"), metadata_id=mid) for mid in metadata_id ] db.add_all(user_meta_entries) db.commit() except SQLAlchemyError as e: db.rollback() return JSONResponse(status_code=500, content=f"Database error: {str(e)}") except Exception as e: return JSONResponse(status_code=500, content=f"Unexpected error: {str(e)}") return {"status": "success", "user_meta": [entry.id for entry in user_meta_entries]} @router.delete("/book_collection/{metadata_id}") async def delete_book_collection( user: user_dependency, db: db_dependency, metadata_id: int ): if user is None: return JSONResponse(status_code=401, content="Authentication Failed") try: # Query to delete the entry based on metadata_id for the authenticated user entry_to_delete = db.query(User_Meta).filter( User_Meta.user_id == user.get("id"), User_Meta.metadata_id == metadata_id ).first() if not entry_to_delete: return JSONResponse(status_code=404, content="Entry not found to delete.") # Delete the entry db.delete(entry_to_delete) db.commit() except SQLAlchemyError as e: db.rollback() # Rollback in case of any database error return JSONResponse(status_code=500, content=f"Database error: {str(e)}") except Exception as e: return JSONResponse( status_code=500, content=f"An unexpected error occurred: {str(e)}" ) return { "status": "success", "deleted_entry": entry_to_delete.id, } @router.delete("/all_collections") async def delete_all_book( user: user_dependency, db: db_dependency, ): if user is None: return JSONResponse(status_code=401, content="Authentication Failed") try: db.query(User_Meta).filter(User_Meta.user_id == user.get("id")).delete( synchronize_session="fetch" ) db.commit() # Commit all deletions return { "status": "success", "delete book collection from": user.get("id"), } except SQLAlchemyError as e: db.rollback() # Rollback in case of any database error return JSONResponse(status_code=500, content=f"Database error: {str(e)}") except Exception as e: return JSONResponse( status_code=500, content=f"An unexpected error occurred: {str(e)}" )