from fastapi import APIRouter, Depends, HTTPException, status from app.schemas.addresses import AddressCreate, AddressResponse from app.core.deps import get_current_user, require_role from app.core.supabase_client import supabase_admin from app.services.simulation import get_colonias router = APIRouter(prefix="/addresses", tags=["addresses"]) def _resolve_route_id(colonia: str) -> str: """Deriva routeId desde colonias-rutas.json; lanza 404 si la colonia no existe.""" mapping = get_colonias() match = next( (c for c in mapping if c.get("colonia", "").lower() == colonia.lower()), None ) if not match: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Colonia '{colonia}' no encontrada. Usa GET /colonias para ver las opciones.", ) return match["routeId"] @router.post("", response_model=AddressResponse, status_code=status.HTTP_201_CREATED) def create_address( body: AddressCreate, current_user: dict = Depends(require_role("citizen", "admin")), ): """Alta de domicilio. El routeId se deriva automáticamente de la colonia elegida.""" route_id = _resolve_route_id(body.colonia) insert_data: dict = { "user_id": current_user["user_id"], "label": body.label, "calle": body.calle, "colonia": body.colonia, "route_id": route_id, "verified": False, } if body.lat is not None: insert_data["lat"] = body.lat if body.lng is not None: insert_data["lng"] = body.lng result = ( supabase_admin.table("addresses") .insert(insert_data) .execute() ) if not result.data: raise HTTPException(status_code=500, detail="No se pudo guardar el domicilio") return result.data[0] @router.get("", response_model=list[AddressResponse]) def list_addresses(current_user: dict = Depends(get_current_user)): """ Lista de domicilios. - Ciudadano: solo sus propios (filtro por user_id en código + RLS en BD). - Admin: todos los domicilios. """ if current_user["role"] == "admin": result = supabase_admin.table("addresses").select("*").execute() else: result = ( supabase_admin.table("addresses") .select("*") .eq("user_id", current_user["user_id"]) .execute() ) return result.data or [] @router.get("/{address_id}", response_model=AddressResponse) def get_address( address_id: str, current_user: dict = Depends(get_current_user), ): """Detalle de un domicilio. El ciudadano solo puede ver los suyos.""" result = ( supabase_admin.table("addresses") .select("*") .eq("id", address_id) .maybe_single() .execute() ) if not result.data: raise HTTPException(status_code=404, detail="Domicilio no encontrado") address = result.data if current_user["role"] != "admin" and address["user_id"] != current_user["user_id"]: raise HTTPException(status_code=403, detail="No tienes acceso a este domicilio") return address @router.get("/{address_id}/unit") def get_address_unit( address_id: str, current_user: dict = Depends(get_current_user), ): """ Devuelve la unidad asignada al domicilio (a través de su ruta). Cadena: addresses.route_id → routes.truck_id → units. El ciudadano sólo puede consultar sus propios domicilios. """ addr_res = ( supabase_admin.table("addresses") .select("id, user_id, route_id") .eq("id", address_id) .maybe_single() .execute() ) if not addr_res.data: raise HTTPException(status_code=404, detail="Domicilio no encontrado") address = addr_res.data if current_user["role"] != "admin" and address["user_id"] != current_user["user_id"]: raise HTTPException(status_code=403, detail="No tienes acceso a este domicilio") route_id = address.get("route_id") if not route_id: raise HTTPException( status_code=404, detail="El domicilio no tiene una ruta asociada", ) route_res = ( supabase_admin.table("routes") .select("id, truck_id") .eq("id", route_id) .maybe_single() .execute() ) if not route_res.data or route_res.data.get("truck_id") is None: raise HTTPException( status_code=404, detail="La ruta asignada no tiene unidad activa", ) truck_id = route_res.data["truck_id"] unit_res = ( supabase_admin.table("units") .select("id, plate, status") .eq("id", truck_id) .maybe_single() .execute() ) if not unit_res.data: raise HTTPException(status_code=404, detail="Unidad no encontrada") return unit_res.data