from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import List, Optional from datetime import datetime, timezone from backend.database import get_db from backend.models import User, ChoreType, ChoreCompletion, UserRole, RecurrenceType from backend.schemas import ChoreTypeOut, ChoreTypeCreate, ChoreTypeUpdate, ChoreCompletionCreate, ChoreCompletionOut from backend.routers.auth import get_current_user, get_admin_user from backend.config import get_current_week_identifier router = APIRouter(prefix="/api/chores", tags=["chores"]) @router.get("/types", response_model=List[ChoreTypeOut]) def list_chore_types(db: Session = Depends(get_db), current_user: User = Depends(get_current_user)): return db.query(ChoreType).order_by(ChoreType.id.asc()).all() @router.post("/types", response_model=ChoreTypeOut) def create_chore_type(chore_in: ChoreTypeCreate, db: Session = Depends(get_db), admin: User = Depends(get_admin_user)): if chore_in.star_reward < 1 or chore_in.star_reward > 5: raise HTTPException(status_code=400, detail="Star reward must be between 1 and 5") if chore_in.recurrence not in [r.value for r in RecurrenceType]: raise HTTPException(status_code=400, detail=f"Invalid recurrence type. Must be daily, weekly, or spontaneous") new_chore = ChoreType( title=chore_in.title, description=chore_in.description, star_reward=chore_in.star_reward, recurrence=chore_in.recurrence, icon=chore_in.icon ) db.add(new_chore) db.commit() db.refresh(new_chore) return new_chore @router.patch("/types/{chore_id}", response_model=ChoreTypeOut) def update_chore_type(chore_id: int, chore_in: ChoreTypeUpdate, db: Session = Depends(get_db), admin: User = Depends(get_admin_user)): chore = db.query(ChoreType).filter(ChoreType.id == chore_id).first() if not chore: raise HTTPException(status_code=404, detail="Chore type not found") if chore_in.title is not None: chore.title = chore_in.title if chore_in.description is not None: chore.description = chore_in.description if chore_in.star_reward is not None: if chore_in.star_reward < 1 or chore_in.star_reward > 5: raise HTTPException(status_code=400, detail="Star reward must be between 1 and 5") chore.star_reward = chore_in.star_reward if chore_in.recurrence is not None: if chore_in.recurrence not in [r.value for r in RecurrenceType]: raise HTTPException(status_code=400, detail="Invalid recurrence type") chore.recurrence = chore_in.recurrence if chore_in.icon is not None: chore.icon = chore_in.icon db.commit() db.refresh(chore) return chore @router.delete("/types/{chore_id}") def delete_chore_type(chore_id: int, db: Session = Depends(get_db), admin: User = Depends(get_admin_user)): chore = db.query(ChoreType).filter(ChoreType.id == chore_id).first() if not chore: raise HTTPException(status_code=404, detail="Chore type not found") db.delete(chore) db.commit() return {"message": "Chore type deleted successfully", "id": chore_id} @router.post("/complete", response_model=ChoreCompletionOut) def complete_chore(payload: ChoreCompletionCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)): chore_type = db.query(ChoreType).filter(ChoreType.id == payload.chore_type_id).first() if not chore_type: raise HTTPException(status_code=404, detail="Chore type not found") week_id = get_current_week_identifier() now_utc = datetime.now(timezone.utc) completion = ChoreCompletion( chore_type_id=chore_type.id, user_id=current_user.id, completed_at=now_utc, stars_earned=chore_type.star_reward, week_identifier=week_id, notes=payload.notes ) db.add(completion) db.commit() db.refresh(completion) return ChoreCompletionOut( id=completion.id, chore_type_id=completion.chore_type_id, user_id=completion.user_id, completed_at=completion.completed_at, stars_earned=completion.stars_earned, week_identifier=completion.week_identifier, notes=completion.notes, user_name=current_user.name, user_avatar=current_user.avatar_url, chore_title=chore_type.title, chore_icon=chore_type.icon ) @router.get("/completions", response_model=List[ChoreCompletionOut]) def get_recent_completions(week: Optional[str] = None, user_id: Optional[int] = None, limit: int = 50, db: Session = Depends(get_db), current_user: User = Depends(get_current_user)): query = db.query(ChoreCompletion) if week: query = query.filter(ChoreCompletion.week_identifier == week) if user_id: query = query.filter(ChoreCompletion.user_id == user_id) completions = query.order_by(ChoreCompletion.completed_at.desc()).limit(limit).all() result = [] for c in completions: result.append(ChoreCompletionOut( id=c.id, chore_type_id=c.chore_type_id, user_id=c.user_id, completed_at=c.completed_at, stars_earned=c.stars_earned, week_identifier=c.week_identifier, notes=c.notes, user_name=c.user.name if c.user else "Unknown", user_avatar=c.user.avatar_url if c.user else None, chore_title=c.chore_type.title if c.chore_type else "Chore", chore_icon=c.chore_type.icon if c.chore_type else "CheckSquare" )) return result