from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import text from app.db.session import get_db from app.api.deps import get_current_user from app.services.matching_service import matching_service from app.services.config_service import config router = APIRouter() @router.get("/match") async def match_service( lat: float, lng: float, radius: int = 20, db: AsyncSession = Depends(get_db), current_user = Depends(get_current_user) ): # 1. SQL lekérdezés: Haversine-formula a távolság számításhoz # 6371 a Föld sugara km-ben query = text(""" SELECT o.id, o.name, ol.latitude, ol.longitude, ol.label as location_name, (6371 * 2 * ASIN(SQRT( POWER(SIN((RADIANS(ol.latitude) - RADIANS(:lat)) / 2), 2) + COS(RADIANS(:lat)) * COS(RADIANS(ol.latitude)) * POWER(SIN((RADIANS(ol.longitude) - RADIANS(:lng)) / 2), 2) ))) AS distance FROM data.organizations o JOIN data.organization_locations ol ON o.id = ol.organization_id WHERE o.org_type = 'SERVICE' AND o.is_active = True HAVING (6371 * 2 * ASIN(SQRT( POWER(SIN((RADIANS(ol.latitude) - RADIANS(:lat)) / 2), 2) + COS(RADIANS(:lat)) * COS(RADIANS(ol.latitude)) * POWER(SIN((RADIANS(ol.longitude) - RADIANS(:lng)) / 2), 2) ))) <= :radius ORDER BY distance ASC """) result = await db.execute(query, {"lat": lat, "lng": lng, "radius": radius}) # Adatok átalakítása a MatchingService számára (mock rating-et adunk hozzá, amíg nincs review tábla) services_to_rank = [] for row in result.all(): services_to_rank.append({ "id": row.id, "name": row.name, "distance": row.distance, "rating": 4.5, # Alapértelmezett, amíg nincs kész az értékelési rendszer "tier": "gold" if row.id == 1 else "free" # Példa logika }) if not services_to_rank: return {"status": "no_results", "message": "Nem található szerviz a megadott körzetben."} # 2. Limit lekérése a beállításokból limit = await config.get_setting('match_limit_default', default=5) # 3. Okos rangsorolás (Admin súlyozás alapján) ranked_results = await matching_service.rank_services(services_to_rank) return { "user_location": {"lat": lat, "lng": lng}, "radius_km": radius, "results": ranked_results[:limit] }