package search import ( "log/slog" "net/http" "strings" "github.com/jackc/pgx/v5/pgxpool" "github.com/ultisuite/ulti-backend/internal/api/apiresponse" "github.com/ultisuite/ulti-backend/internal/api/apivalidate" "github.com/ultisuite/ulti-backend/internal/api/middleware" "github.com/ultisuite/ulti-backend/internal/api/query" "github.com/ultisuite/ulti-backend/internal/nextcloud" ) type Handler struct { svc *Service logger *slog.Logger } type Options struct { Nextcloud *nextcloud.Client Engine string MeilisearchURL string MeilisearchKey string MeilisearchIndex string TypesenseURL string TypesenseKey string TypesenseCollection string } func NewHandler(db *pgxpool.Pool, opts Options) *Handler { return &Handler{ svc: NewService(db, ServiceOptions{ Nextcloud: opts.Nextcloud, Engine: opts.Engine, MeilisearchURL: opts.MeilisearchURL, MeilisearchKey: opts.MeilisearchKey, MeilisearchIndex: opts.MeilisearchIndex, TypesenseURL: opts.TypesenseURL, TypesenseKey: opts.TypesenseKey, TypesenseCollection: opts.TypesenseCollection, }), logger: slog.Default().With("component", "search"), } } func (h *Handler) Search(w http.ResponseWriter, r *http.Request) { claims := middleware.ClaimsFromContext(r.Context()) q := r.URL.Query().Get("q") if verr := validateSearchQuery(q); verr != nil { apiresponse.WriteError(w, r, http.StatusBadRequest, apiresponse.CodeInvalidQueryParam, "invalid query parameters", verr.Details) return } types := r.URL.Query().Get("types") if verr := validateSearchTypes(types); verr != nil { apiresponse.WriteError(w, r, http.StatusBadRequest, apiresponse.CodeInvalidQueryParam, "invalid query parameters", verr.Details) return } params, err := query.ParseListRequest(r) if err != nil { apivalidate.WriteQueryError(w, r, err) return } filters := SearchFilters{ AccountID: strings.TrimSpace(r.URL.Query().Get("account_id")), } result, err := h.svc.Search(r.Context(), claims.Sub, q, types, params, filters) if err != nil { h.logger.Error("search", "error", err) apivalidate.WriteInternal(w, r) return } apiresponse.WriteJSON(w, http.StatusOK, result) }