from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from app.db.base import get_db from app.models.product import Category, Product from app.schemas.product import CategoryCreate, CategoryResponse from app.schemas.auth import AuthResponse from app.core.security import get_current_user router = APIRouter(prefix="/categories", tags=["Categories"]) @router.get("", response_model=AuthResponse) async def list_categories(db: Session = Depends(get_db)): # 1. Fetch all categories all_categories = db.query(Category).all() # 2. Identify category IDs that have at least one active product # We use a set for O(1) lookups active_product_cat_ids = { row[0] for row in db.query(Product.category_id) .filter(Product.is_active == True) .distinct() .all() if row[0] is not None } # 3. Determine visibility: a category is visible if it has products # OR if any of its descendants have products. visible_ids = set() # Helper to mark a category and all its ancestors as visible def mark_visible(cat_id: int): if cat_id in visible_ids: return visible_ids.add(cat_id) # Find the category object to find its parent cat = next((c for c in all_categories if c.id == cat_id), None) if cat and cat.parent_id: mark_visible(cat.parent_id) for cat_id in active_product_cat_ids: mark_visible(cat_id) # 4. Filter and Sort filtered_categories = [c for c in all_categories if c.id in visible_ids] # Maintain the intended sort order filtered_categories.sort(key=lambda x: x.sort_order) items = [CategoryResponse.model_validate(c).model_dump() for c in filtered_categories] return AuthResponse( isSuccess=True, value={"items": items}, statusCode=200, ) @router.post("", response_model=AuthResponse, status_code=status.HTTP_201_CREATED) async def create_category( request: CategoryCreate, user_id: int = Depends(get_current_user), db: Session = Depends(get_db), ): category = Category( name_ar=request.name_ar, name_en=request.name_en, icon=request.icon, sort_order=request.sort_order, ) db.add(category) db.commit() db.refresh(category) return AuthResponse( isSuccess=True, value={"category_id": category.id}, statusCode=201, )