from typing import Any, List, Optional from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from app.api.deps import get_current_active_admin, get_current_active_user from app.db.session import get_db from app.models.user import User from app.schemas.bible_book import BibleBook, Testament from app.schemas.question import ( Question, QuestionCategory, QuestionCreate, QuestionDifficulty, QuestionUpdate, ) from app.services import question as question_service router = APIRouter() @router.get("/", response_model=List[Question]) def read_questions( db: Session = Depends(get_db), skip: int = 0, limit: int = 100, category_id: Optional[int] = None, difficulty_id: Optional[int] = None, bible_book_id: Optional[int] = None, current_user: User = Depends(get_current_active_user), ) -> Any: """ Retrieve questions with optional filtering. """ questions = question_service.get_multi( db, skip=skip, limit=limit, category_id=category_id, difficulty_id=difficulty_id, bible_book_id=bible_book_id, ) return questions @router.post("/", response_model=Question) def create_question( *, db: Session = Depends(get_db), question_in: QuestionCreate, current_user: User = Depends(get_current_active_admin), ) -> Any: """ Create new question with options. Admin only. """ # Validate that at least one option is marked as correct if not any(option.is_correct for option in question_in.options): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="At least one option must be marked as correct", ) question = question_service.create(db, obj_in=question_in) return question @router.get("/{question_id}", response_model=Question) def read_question( *, db: Session = Depends(get_db), question_id: int, current_user: User = Depends(get_current_active_user), ) -> Any: """ Get question by ID. """ question = question_service.get_by_id(db, question_id=question_id) if not question: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Question not found", ) return question @router.put("/{question_id}", response_model=Question) def update_question( *, db: Session = Depends(get_db), question_id: int, question_in: QuestionUpdate, current_user: User = Depends(get_current_active_admin), ) -> Any: """ Update a question. Admin only. """ question = question_service.get_by_id(db, question_id=question_id) if not question: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Question not found", ) # If options are being updated, validate that at least one is correct if question_in.options: # Identify which options have is_correct field set options_with_is_correct = [ opt for opt in question_in.options if opt.is_correct is not None ] # If any options have is_correct field set, at least one must be True if options_with_is_correct and not any(opt.is_correct for opt in options_with_is_correct): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="At least one option must be marked as correct", ) question = question_service.update(db, db_obj=question, obj_in=question_in) return question @router.delete("/{question_id}", status_code=status.HTTP_204_NO_CONTENT, response_model=None) def delete_question( *, db: Session = Depends(get_db), question_id: int, current_user: User = Depends(get_current_active_admin), ) -> Any: """ Delete a question. Admin only. """ question = question_service.get_by_id(db, question_id=question_id) if not question: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Question not found", ) question_service.remove(db, question_id=question_id) return None # Endpoints for categories, difficulties, and Bible books @router.get("/categories/", response_model=List[QuestionCategory]) def read_categories( db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user), ) -> Any: """ Retrieve all question categories. """ return question_service.get_all_categories(db) @router.get("/difficulties/", response_model=List[QuestionDifficulty]) def read_difficulties( db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user), ) -> Any: """ Retrieve all question difficulties. """ return question_service.get_all_difficulties(db) @router.get("/bible-books/", response_model=List[BibleBook]) def read_bible_books( db: Session = Depends(get_db), testament: Optional[Testament] = None, current_user: User = Depends(get_current_active_user), ) -> Any: """ Retrieve all Bible books, optionally filtered by testament. """ if testament: return question_service.get_bible_books_by_testament(db, testament=testament.value) return question_service.get_all_bible_books(db)