from typing import List, Optional from fastapi import APIRouter, Depends, HTTPException, Query, BackgroundTasks from sqlalchemy.orm import Session from app.core.database import get_db from app.api.deps import get_current_user from app.tasks.background_tasks import process_marketplace_import from middleware.decorators import rate_limit from models.api_models import MarketplaceImportJobResponse, MarketplaceImportRequest from models.database_models import User, MarketplaceImportJob, Shop from datetime import datetime import logging router = APIRouter() logger = logging.getLogger(__name__) # Admin-only routes @router.get("/admin/users", response_model=List[UserResponse]) def get_all_users( skip: int = Query(0, ge=0), limit: int = Query(100, ge=1, le=1000), db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_user) ): """Get all users (Admin only)""" users = db.query(User).offset(skip).limit(limit).all() return [UserResponse.model_validate(user) for user in users] @router.put("/admin/users/{user_id}/status") def toggle_user_status( user_id: int, db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_user) ): """Toggle user active status (Admin only)""" user = db.query(User).filter(User.id == user_id).first() if not user: raise HTTPException(status_code=404, detail="User not found") if user.id == current_admin.id: raise HTTPException(status_code=400, detail="Cannot deactivate your own account") user.is_active = not user.is_active user.updated_at = datetime.utcnow() db.commit() db.refresh(user) status = "activated" if user.is_active else "deactivated" return {"message": f"User {user.username} has been {status}"} @router.get("/admin/shops", response_model=ShopListResponse) def get_all_shops_admin( skip: int = Query(0, ge=0), limit: int = Query(100, ge=1, le=1000), db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_user) ): """Get all shops with admin view (Admin only)""" total = db.query(Shop).count() shops = db.query(Shop).offset(skip).limit(limit).all() return ShopListResponse( shops=shops, total=total, skip=skip, limit=limit ) @router.put("/admin/shops/{shop_id}/verify") def verify_shop( shop_id: int, db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_user) ): """Verify/unverify shop (Admin only)""" shop = db.query(Shop).filter(Shop.id == shop_id).first() if not shop: raise HTTPException(status_code=404, detail="Shop not found") shop.is_verified = not shop.is_verified shop.updated_at = datetime.utcnow() db.commit() db.refresh(shop) status = "verified" if shop.is_verified else "unverified" return {"message": f"Shop {shop.shop_code} has been {status}"} @router.put("/admin/shops/{shop_id}/status") def toggle_shop_status( shop_id: int, db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_user) ): """Toggle shop active status (Admin only)""" shop = db.query(Shop).filter(Shop.id == shop_id).first() if not shop: raise HTTPException(status_code=404, detail="Shop not found") shop.is_active = not shop.is_active shop.updated_at = datetime.utcnow() db.commit() db.refresh(shop) status = "activated" if shop.is_active else "deactivated" return {"message": f"Shop {shop.shop_code} has been {status}"} @router.get("/admin/marketplace-import-jobs", response_model=List[MarketplaceImportJobResponse]) def get_all_marketplace_import_jobs( marketplace: Optional[str] = Query(None), shop_name: Optional[str] = Query(None), status: Optional[str] = Query(None), skip: int = Query(0, ge=0), limit: int = Query(100, ge=1, le=100), db: Session = Depends(get_db), current_admin: User = Depends(get_current_admin_user) ): """Get all marketplace import jobs (Admin only)""" query = db.query(MarketplaceImportJob) # Apply filters if marketplace: query = query.filter(MarketplaceImportJob.marketplace.ilike(f"%{marketplace}%")) if shop_name: query = query.filter(MarketplaceImportJob.shop_name.ilike(f"%{shop_name}%")) if status: query = query.filter(MarketplaceImportJob.status == status) # Order by creation date and apply pagination jobs = query.order_by(MarketplaceImportJob.created_at.desc()).offset(skip).limit(limit).all() return [ MarketplaceImportJobResponse( job_id=job.id, status=job.status, marketplace=job.marketplace, shop_name=job.shop_name, imported=job.imported_count or 0, updated=job.updated_count or 0, total_processed=job.total_processed or 0, error_count=job.error_count or 0, error_message=job.error_message, created_at=job.created_at, started_at=job.started_at, completed_at=job.completed_at ) for job in jobs ]