package handler import ( "bugulma/backend/internal/service" "net/http" "strconv" "github.com/gin-gonic/gin" ) // GeospatialHandler handles geospatial queries type GeospatialHandler struct { service *service.GeospatialService } // NewGeospatialHandler creates a new geospatial handler func NewGeospatialHandler(service *service.GeospatialService) *GeospatialHandler { return &GeospatialHandler{service: service} } // FindNearbySites finds sites within a radius // @Summary Find nearby sites // @Tags geospatial // @Produce json // @Param lat query float64 true "Latitude" // @Param lng query float64 true "Longitude" // @Param radius query float64 false "Radius in kilometers" default(5.0) // @Param limit query int false "Maximum results" default(50) // @Success 200 {array} service.SpatialResult // @Router /api/geospatial/nearby-sites [get] func (h *GeospatialHandler) FindNearbySites(c *gin.Context) { latStr := c.Query("lat") lngStr := c.Query("lng") radiusStr := c.DefaultQuery("radius", "5.0") limitStr := c.DefaultQuery("limit", "50") lat, err := strconv.ParseFloat(latStr, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid latitude"}) return } lng, err := strconv.ParseFloat(lngStr, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid longitude"}) return } radius, _ := strconv.ParseFloat(radiusStr, 64) limit, _ := strconv.Atoi(limitStr) query := service.SpatialQuery{ CenterLat: lat, CenterLng: lng, RadiusKm: radius, MaxResults: limit, } results, err := h.service.FindNearbySites(c.Request.Context(), query) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, results) } // GetSpatialStatistics returns spatial statistics // @Summary Get spatial statistics // @Tags geospatial // @Produce json // @Success 200 {object} map[string]interface{} // @Router /api/geospatial/statistics [get] func (h *GeospatialHandler) GetSpatialStatistics(c *gin.Context) { stats, err := h.service.GetSpatialStatistics(c.Request.Context()) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, stats) } // GetSpatialClusters finds spatial clusters of sites // @Summary Get spatial clusters // @Tags geospatial // @Produce json // @Param min_points query int false "Minimum points per cluster" default(3) // @Param radius_km query float64 false "Cluster radius in km" default(1.0) // @Success 200 {array} service.SpatialCluster // @Router /api/geospatial/clusters [get] func (h *GeospatialHandler) GetSpatialClusters(c *gin.Context) { minPointsStr := c.DefaultQuery("min_points", "3") radiusStr := c.DefaultQuery("radius_km", "1.0") minPoints, _ := strconv.Atoi(minPointsStr) radius, _ := strconv.ParseFloat(radiusStr, 64) clusters, err := h.service.FindSpatialClusters(c.Request.Context(), minPoints, radius) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, clusters) }