from fastapi import APIRouter, Depends, HTTPException, status from pydantic import BaseModel from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.dependencies import get_db, get_current_user from app.models.rule import RuleItem from app.models.user import User router = APIRouter(prefix="/api/rules", tags=["rules"]) class RuleItemOut(BaseModel): id: int text: str order_index: int model_config = {"from_attributes": True} class RuleItemCreate(BaseModel): text: str order_index: int = 0 class RuleItemUpdate(BaseModel): text: str | None = None order_index: int | None = None class ReorderEntry(BaseModel): id: int order_index: int @router.get("", response_model=list[RuleItemOut]) async def list_rules( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(RuleItem) .where(RuleItem.user_id == current_user.id) .order_by(RuleItem.order_index, RuleItem.id) ) return result.scalars().all() @router.post("", response_model=RuleItemOut, status_code=status.HTTP_201_CREATED) async def create_rule( body: RuleItemCreate, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): item = RuleItem(user_id=current_user.id, text=body.text, order_index=body.order_index) db.add(item) await db.commit() await db.refresh(item) return item @router.patch("/{item_id}", response_model=RuleItemOut) async def update_rule( item_id: int, body: RuleItemUpdate, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(RuleItem).where( RuleItem.id == item_id, RuleItem.user_id == current_user.id, ) ) item = result.scalar_one_or_none() if not item: raise HTTPException(status_code=404, detail="Rule not found") if body.text is not None: item.text = body.text if body.order_index is not None: item.order_index = body.order_index await db.commit() await db.refresh(item) return item @router.put("/reorder", status_code=status.HTTP_204_NO_CONTENT) async def reorder_rules( body: list[ReorderEntry], current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): ids = [e.id for e in body] result = await db.execute( select(RuleItem).where( RuleItem.id.in_(ids), RuleItem.user_id == current_user.id, ) ) items = {item.id: item for item in result.scalars().all()} for entry in body: if entry.id in items: items[entry.id].order_index = entry.order_index await db.commit() @router.delete("/{item_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_rule( item_id: int, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(RuleItem).where( RuleItem.id == item_id, RuleItem.user_id == current_user.id, ) ) item = result.scalar_one_or_none() if not item: raise HTTPException(status_code=404, detail="Rule not found") await db.delete(item) await db.commit()