from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.models.user import User from app.models.project import Project from app.models.character import Character from app.schemas.character import CharacterCreate, CharacterUpdate, CharacterResponse from app.services.auth import get_current_user router = APIRouter(prefix="/api/projects/{project_id}/characters", tags=["characters"]) async def _get_user_project(project_id: int, user: User, db: AsyncSession) -> Project: result = await db.execute( select(Project).where(Project.id == project_id, Project.user_id == user.id) ) project = result.scalar_one_or_none() if not project: raise HTTPException(status_code=404, detail="Project not found") return project @router.get("", response_model=list[CharacterResponse]) async def list_characters( project_id: int, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): await _get_user_project(project_id, user, db) result = await db.execute( select(Character) .where(Character.project_id == project_id) .order_by(Character.name) ) return list(result.scalars().all()) @router.post("", response_model=CharacterResponse, status_code=201) async def create_character( project_id: int, data: CharacterCreate, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): await _get_user_project(project_id, user, db) character = Character(project_id=project_id, **data.model_dump(exclude_none=True)) db.add(character) await db.commit() await db.refresh(character) return character @router.patch("/{character_id}", response_model=CharacterResponse) async def update_character( project_id: int, character_id: int, data: CharacterUpdate, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): await _get_user_project(project_id, user, db) result = await db.execute( select(Character).where(Character.id == character_id, Character.project_id == project_id) ) character = result.scalar_one_or_none() if not character: raise HTTPException(status_code=404, detail="Character not found") for key, value in data.model_dump(exclude_none=True).items(): setattr(character, key, value) await db.commit() await db.refresh(character) return character