from fastapi import APIRouter, HTTPException, Depends, Query from app.models import ChatbotPublicResponse, MarketplaceResponse, RatingCreate from app.database import get_supabase from app.dependencies import get_optional_user, get_current_user from typing import Optional import logging logger = logging.getLogger(__name__) router = APIRouter(prefix="/marketplace", tags=["Marketplace"]) # ═══════════════════════════════════════════════════════════════════════════════ # CATEGORIES & INDUSTRIES — Expanded to support all business types: # Individuals, small businesses (restaurants, barbershops, malls, phone shops), # and large enterprises. # ═══════════════════════════════════════════════════════════════════════════════ CATEGORIES = [ # What the chatbot does "Customer Support", "Sales Assistant", "FAQ & Knowledge Base", "Appointment Booking", "Order & Delivery Tracking", "Product Recommendations", "Lead Generation", "Onboarding & Training", "Feedback & Surveys", "Personal Assistant", "Consultation", "Other", ] INDUSTRIES = [ # Small businesses / Local services "Restaurant & Food", "Beauty & Barbershop", "Retail & Shopping", "Phone & Electronics", "Automotive & Repair", "Fitness & Wellness", "Cleaning & Home Services", "Photography & Events", # Professional services "Healthcare & Medical", "Legal & Law", "Finance & Insurance", "Real Estate", "Accounting & Tax", # Tech & Digital "Technology & SaaS", "E-commerce", "Agency & Marketing", # Education & Non-profit "Education & Training", "Non-profit & NGO", # Large scale "Hospitality & Hotels", "Travel & Tourism", "Manufacturing", "Logistics & Transport", "Agriculture", "Government", # Personal "Personal Brand", "Freelancer & Consultant", "Other", ] @router.get("/chatbots", response_model=MarketplaceResponse) async def list_marketplace_chatbots( category: Optional[str] = Query(None), industry: Optional[str] = Query(None), language: Optional[str] = Query(None), search: Optional[str] = Query(None), page: int = Query(1, ge=1), limit: int = Query(20, ge=1, le=100), user=Depends(get_optional_user), ): supabase = get_supabase() query = supabase.table("chatbots").select( "*, companies(name, logo_url)" ).eq("is_published", True).eq("visibility", "published") if category: query = query.eq("category", category) if industry: query = query.eq("industry", industry) if search: query = query.ilike("name", f"%{search}%") offset = (page - 1) * limit result = query.order("created_at", desc=True).range(offset, offset + limit - 1).execute() all_result = supabase.table("chatbots").select("id", count="exact").eq("is_published", True).execute() total = all_result.count or 0 chatbots = [] for c in (result.data or []): company_data = c.get("companies") or {} chatbots.append( ChatbotPublicResponse( id=c["id"], name=c["name"], description=c.get("description"), category=c.get("category"), industry=c.get("industry"), languages=c.get("languages", ["en"]), primary_color=c.get("primary_color", "#6366f1"), welcome_message=c.get("welcome_message", "Hello!"), logo_url=c.get("logo_url"), average_rating=c.get("average_rating"), total_conversations=c.get("total_conversations", 0), company_name=company_data.get("name"), company_logo=company_data.get("logo_url"), created_at=c.get("created_at"), published_at=c.get("published_at"), ) ) return MarketplaceResponse( chatbots=chatbots, total=total, page=page, limit=limit, has_more=(offset + limit < total), ) @router.get("/chatbots/{chatbot_id}", response_model=ChatbotPublicResponse) async def get_marketplace_chatbot(chatbot_id: str, user=Depends(get_optional_user)): supabase = get_supabase() result = supabase.table("chatbots").select( "*, companies(name, logo_url)" ).eq("id", chatbot_id).eq("is_published", True).execute() if not result.data: raise HTTPException(status_code=404, detail="Chatbot not found") c = result.data[0] company_data = c.get("companies") or {} conv_count = supabase.table("conversations").select("id", count="exact") \ .eq("chatbot_id", chatbot_id).execute() return ChatbotPublicResponse( id=c["id"], name=c["name"], description=c.get("description"), category=c.get("category"), industry=c.get("industry"), languages=c.get("languages", ["en"]), primary_color=c.get("primary_color", "#6366f1"), welcome_message=c.get("welcome_message", "Hello!"), logo_url=c.get("logo_url"), average_rating=c.get("average_rating"), total_conversations=conv_count.count or 0, company_name=company_data.get("name"), company_logo=company_data.get("logo_url"), created_at=c.get("created_at"), published_at=c.get("published_at"), ) @router.get("/categories") async def get_categories(): return {"categories": CATEGORIES, "industries": INDUSTRIES} @router.post("/chatbots/{chatbot_id}/rate") async def rate_chatbot( chatbot_id: str, rating: RatingCreate, user=Depends(get_current_user), ): supabase = get_supabase() chatbot = supabase.table("chatbots").select("id, average_rating").eq("id", chatbot_id).eq("is_published", True).execute() if not chatbot.data: raise HTTPException(status_code=404, detail="Chatbot not found") # Simple rating update (average) current = chatbot.data[0].get("average_rating") or rating.rating new_avg = (current + rating.rating) / 2 supabase.table("chatbots").update({"average_rating": round(new_avg, 1)}).eq("id", chatbot_id).execute() return {"message": "Rating submitted", "new_average": round(new_avg, 1)}