from typing import List, Optional from fastapi import APIRouter, Depends, Query from sqlalchemy.orm import Session from backend.app.core.database import get_db from backend.app.repositories.users import UserRepository from backend.app.schemas.auth import WorkerSearchResult router = APIRouter(prefix="/workers", tags=["workers"]) def calculate_ai_score( rating: float, completion_rate: int, distance: float, online: bool, verified: bool ) -> int: """ Simulated AI ranking score calculation. Formula: rating * 7 + completion_rate * 0.25 + online (25 pts) + verified (15 pts) + distance (max 25 - distance * 3) """ online_score = 25 if online else 0 verified_score = 15 if verified else 0 distance_score = max(0.0, 25.0 - float(distance) * 3.0) score = (float(rating) * 7.0) + (int(completion_rate) * 0.25) + online_score + verified_score + distance_score return round(score) @router.get("", response_model=List[WorkerSearchResult]) def search_workers( skill: Optional[str] = Query("All", description="Filter by worker skill type"), radius: Optional[float] = Query(5.0, description="Max search radius in kilometers"), online: Optional[str] = Query("yes", description="Filter: 'yes' for online only, 'all' for all"), q: Optional[str] = Query("", alias="query", description="Search by name or skill query text"), db: Session = Depends(get_db) ): """ Search and rank construction workers using the location-aware AI ranking algorithm. """ user_repo = UserRepository(db) # Resolve online boolean filter online_only = (online == "yes") # Query database workers matching filters workers = user_repo.get_all_workers( skill=skill, radius=radius, online_only=online_only ) results = [] text_filter = q.strip().lower() for user in workers: prof = user.worker_profile if not prof: continue # Text query filtering (by name or skill) if text_filter and text_filter not in f"{user.name} {prof.skill}".lower(): continue # Compute dynamic match score score = calculate_ai_score( rating=prof.rating, completion_rate=prof.completion_rate, distance=prof.distance, online=prof.online, verified=prof.verified ) results.append( WorkerSearchResult( id=user.id, name=user.name, phone=user.phone, city=user.city, skill=prof.skill, rate=prof.rate, rating=prof.rating, distance=prof.distance, online=prof.online, verified=prof.verified, completed_jobs=prof.completed_jobs, completion_rate=prof.completion_rate, map_x=prof.map_x, map_y=prof.map_y, ai_score=score ) ) # Sort results in descending order of AI Match Score results.sort(key=lambda w: w.ai_score, reverse=True) return results