package search import ( "errors" "net/http" "strconv" "github.com/ultisuite/ulti-backend/internal/api/apiresponse" "github.com/ultisuite/ulti-backend/internal/api/middleware" "github.com/ultisuite/ulti-backend/internal/contacts/discovery" ) type WebHandler struct { discovery *discovery.Service } func NewWebHandler(discovery *discovery.Service) *WebHandler { return &WebHandler{discovery: discovery} } func (h *WebHandler) Search(w http.ResponseWriter, r *http.Request) { if h.discovery == nil { apiresponse.WriteError(w, r, http.StatusServiceUnavailable, apiresponse.CodeInternal, "web search unavailable", nil) return } claims := middleware.ClaimsFromContext(r.Context()) query := r.URL.Query().Get("q") if query == "" { apiresponse.WriteError(w, r, http.StatusBadRequest, apiresponse.CodeInvalidQueryParam, "q is required", nil) return } count := 5 if raw := r.URL.Query().Get("count"); raw != "" { parsed, err := strconv.Atoi(raw) if err != nil || parsed <= 0 { apiresponse.WriteError(w, r, http.StatusBadRequest, apiresponse.CodeInvalidQueryParam, "invalid count", nil) return } count = parsed } results, err := h.discovery.SearchWeb(r.Context(), claims.Sub, query, count) if err != nil { if errors.Is(err, discovery.ErrWebSearchNotConfigured) { apiresponse.WriteError(w, r, http.StatusServiceUnavailable, "web_search_not_configured", "web search provider not configured", nil) return } apiresponse.WriteError(w, r, http.StatusBadGateway, apiresponse.CodeInternal, err.Error(), nil) return } apiresponse.WriteJSON(w, http.StatusOK, map[string]any{ "query": query, "results": results, }) }