from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from sqlalchemy import or_, and_ from typing import List, Optional from datetime import datetime from app.db.base import get_db from app.models.user import User, Connection from app.models.ministry import MinistryMember from app.models.prayer import ( PrayerRequest, Prayer, PrayerPrivacyLevel, PrayerStatus, PrayerCategory, ) from app.schemas.prayer import ( PrayerRequestCreate, PrayerRequestUpdate, PrayerRequestResponse, PrayerCreate, PrayerResponse, PrayerStats, ) from app.api.auth import get_current_user router = APIRouter() def can_view_prayer_request( prayer_request: PrayerRequest, current_user: User, db: Session ) -> bool: """Check if user can view a prayer request based on privacy level""" if prayer_request.requester_id == current_user.id: return True if prayer_request.privacy_level == PrayerPrivacyLevel.PUBLIC: return True if prayer_request.privacy_level == PrayerPrivacyLevel.PRIVATE: return False if prayer_request.privacy_level == PrayerPrivacyLevel.CONNECTIONS_ONLY: # Check if users are connected connection = ( db.query(Connection) .filter( or_( and_( Connection.sender_id == current_user.id, Connection.receiver_id == prayer_request.requester_id, ), and_( Connection.sender_id == prayer_request.requester_id, Connection.receiver_id == current_user.id, ), ), Connection.status == "accepted", ) .first() ) return connection is not None if ( prayer_request.privacy_level == PrayerPrivacyLevel.MINISTRY_ONLY and prayer_request.ministry_id ): # Check if user is in the same ministry membership = ( db.query(MinistryMember) .filter( MinistryMember.ministry_id == prayer_request.ministry_id, MinistryMember.user_id == current_user.id, MinistryMember.is_active, ) .first() ) return membership is not None return False @router.post("/", response_model=PrayerRequestResponse) def create_prayer_request( prayer_request: PrayerRequestCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Create a new prayer request""" # Validate ministry access if ministry_only privacy if ( prayer_request.privacy_level == PrayerPrivacyLevel.MINISTRY_ONLY and prayer_request.ministry_id ): membership = ( db.query(MinistryMember) .filter( MinistryMember.ministry_id == prayer_request.ministry_id, MinistryMember.user_id == current_user.id, MinistryMember.is_active, ) .first() ) if not membership: raise HTTPException( status_code=403, detail="Must be a ministry member to create ministry-only requests", ) db_request = PrayerRequest(**prayer_request.dict(), requester_id=current_user.id) db.add(db_request) db.commit() db.refresh(db_request) # Add response metadata db_request.requester_name = ( f"{current_user.first_name} {current_user.last_name}" if not db_request.is_anonymous else "Anonymous" ) db_request.prayer_count = 0 db_request.has_prayed = False if db_request.ministry_id: db_request.ministry_name = db_request.ministry.name return db_request @router.get("/", response_model=List[PrayerRequestResponse]) def get_prayer_requests( skip: int = 0, limit: int = 100, category: Optional[PrayerCategory] = None, status: Optional[PrayerStatus] = None, privacy_level: Optional[PrayerPrivacyLevel] = None, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Get prayer requests based on user's access level""" query = db.query(PrayerRequest) # Apply filters if category: query = query.filter(PrayerRequest.category == category) if status: query = query.filter(PrayerRequest.status == status) if privacy_level: query = query.filter(PrayerRequest.privacy_level == privacy_level) prayer_requests = ( query.order_by(PrayerRequest.created_at.desc()).offset(skip).limit(limit).all() ) # Filter based on privacy and add metadata accessible_requests = [] for request in prayer_requests: if can_view_prayer_request(request, current_user, db): # Add metadata request.requester_name = ( f"{request.requester.first_name} {request.requester.last_name}" if not request.is_anonymous else "Anonymous" ) request.prayer_count = ( db.query(Prayer).filter(Prayer.prayer_request_id == request.id).count() ) request.has_prayed = ( db.query(Prayer) .filter( Prayer.prayer_request_id == request.id, Prayer.prayer_warrior_id == current_user.id, ) .first() is not None ) if request.ministry_id: request.ministry_name = request.ministry.name accessible_requests.append(request) return accessible_requests @router.get("/my-requests", response_model=List[PrayerRequestResponse]) def get_my_prayer_requests( db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """Get current user's prayer requests""" requests = ( db.query(PrayerRequest) .filter(PrayerRequest.requester_id == current_user.id) .order_by(PrayerRequest.created_at.desc()) .all() ) for request in requests: request.requester_name = f"{current_user.first_name} {current_user.last_name}" request.prayer_count = ( db.query(Prayer).filter(Prayer.prayer_request_id == request.id).count() ) request.has_prayed = False # Can't pray for own request if request.ministry_id: request.ministry_name = request.ministry.name return requests @router.get("/{request_id}", response_model=PrayerRequestResponse) def get_prayer_request( request_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Get specific prayer request""" prayer_request = ( db.query(PrayerRequest).filter(PrayerRequest.id == request_id).first() ) if not prayer_request: raise HTTPException(status_code=404, detail="Prayer request not found") if not can_view_prayer_request(prayer_request, current_user, db): raise HTTPException( status_code=403, detail="Access denied to this prayer request" ) # Add metadata prayer_request.requester_name = ( f"{prayer_request.requester.first_name} {prayer_request.requester.last_name}" if not prayer_request.is_anonymous else "Anonymous" ) prayer_request.prayer_count = ( db.query(Prayer).filter(Prayer.prayer_request_id == prayer_request.id).count() ) prayer_request.has_prayed = ( db.query(Prayer) .filter( Prayer.prayer_request_id == prayer_request.id, Prayer.prayer_warrior_id == current_user.id, ) .first() is not None ) if prayer_request.ministry_id: prayer_request.ministry_name = prayer_request.ministry.name return prayer_request @router.put("/{request_id}", response_model=PrayerRequestResponse) def update_prayer_request( request_id: int, prayer_update: PrayerRequestUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Update prayer request (owner only)""" prayer_request = ( db.query(PrayerRequest).filter(PrayerRequest.id == request_id).first() ) if not prayer_request: raise HTTPException(status_code=404, detail="Prayer request not found") if prayer_request.requester_id != current_user.id: raise HTTPException( status_code=403, detail="Can only update own prayer requests" ) # Handle status changes update_data = prayer_update.dict(exclude_unset=True) if "status" in update_data and update_data["status"] == PrayerStatus.ANSWERED: if not update_data.get("answer_description"): raise HTTPException( status_code=400, detail="Answer description required when marking as answered", ) update_data["answered_at"] = datetime.utcnow() # Update fields for field, value in update_data.items(): setattr(prayer_request, field, value) db.commit() db.refresh(prayer_request) return prayer_request @router.post("/{request_id}/pray", response_model=PrayerResponse) def pray_for_request( request_id: int, prayer: PrayerCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Pray for a prayer request""" prayer_request = ( db.query(PrayerRequest).filter(PrayerRequest.id == request_id).first() ) if not prayer_request: raise HTTPException(status_code=404, detail="Prayer request not found") if not can_view_prayer_request(prayer_request, current_user, db): raise HTTPException( status_code=403, detail="Access denied to this prayer request" ) if prayer_request.requester_id == current_user.id: raise HTTPException(status_code=400, detail="Cannot pray for your own request") # Check if already prayed existing_prayer = ( db.query(Prayer) .filter( Prayer.prayer_request_id == request_id, Prayer.prayer_warrior_id == current_user.id, ) .first() ) if existing_prayer: raise HTTPException(status_code=400, detail="Already prayed for this request") db_prayer = Prayer( prayer_request_id=request_id, prayer_warrior_id=current_user.id, message=prayer.message, ) db.add(db_prayer) db.commit() db.refresh(db_prayer) db_prayer.prayer_warrior_name = ( f"{current_user.first_name} {current_user.last_name}" ) return db_prayer @router.get("/{request_id}/prayers", response_model=List[PrayerResponse]) def get_prayers_for_request( request_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): """Get prayers for a specific request""" prayer_request = ( db.query(PrayerRequest).filter(PrayerRequest.id == request_id).first() ) if not prayer_request: raise HTTPException(status_code=404, detail="Prayer request not found") if not can_view_prayer_request(prayer_request, current_user, db): raise HTTPException( status_code=403, detail="Access denied to this prayer request" ) prayers = ( db.query(Prayer) .filter(Prayer.prayer_request_id == request_id) .order_by(Prayer.prayed_at.desc()) .all() ) for prayer in prayers: prayer.prayer_warrior_name = ( f"{prayer.prayer_warrior.first_name} {prayer.prayer_warrior.last_name}" ) return prayers @router.get("/stats/personal", response_model=PrayerStats) def get_personal_prayer_stats( db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """Get personal prayer statistics""" total_requests = db.query(PrayerRequest).count() active_requests = ( db.query(PrayerRequest) .filter(PrayerRequest.status == PrayerStatus.ACTIVE) .count() ) answered_requests = ( db.query(PrayerRequest) .filter(PrayerRequest.status == PrayerStatus.ANSWERED) .count() ) prayers_offered = ( db.query(Prayer).filter(Prayer.prayer_warrior_id == current_user.id).count() ) requests_created = ( db.query(PrayerRequest) .filter(PrayerRequest.requester_id == current_user.id) .count() ) return PrayerStats( total_requests=total_requests, active_requests=active_requests, answered_requests=answered_requests, prayers_offered=prayers_offered, requests_created=requests_created, )