defmodule MusicLibrary.Search do @moduledoc """ Universal search functionality across Records and Artists. This module provides unified search across: - Records in Collection (purchased records) - Records in Wishlist (unpurchased records) - Artists """ alias MusicLibrary.{Artists, Collection, RecordSets, Wishlist} @pagination Application.compile_env!(:music_library, :pagination) @type search_opts :: [limit: non_neg_integer()] @doc """ Performs a universal search across all entity types. Returns a map with grouped results: - :collection - Records in the collection - :wishlist - Records in the wishlist - :artists - Artists """ @spec universal_search(String.t(), search_opts()) :: map() def universal_search(query, opts \\ []) do limit = Keyword.get(opts, :limit, @pagination[:search_preview_limit]) %{ collection: search_collection(query, limit), wishlist: search_wishlist(query, limit), artists: search_artists(query, limit), record_sets: search_record_sets(query, limit) } end @doc """ Searches records in the collection (purchased records). """ @spec search_collection(String.t(), non_neg_integer()) :: [map()] def search_collection(query, limit \\ @pagination[:search_preview_limit]) do Collection.search_records(query, limit: limit) end @doc """ Searches records in the wishlist (unpurchased records). """ @spec search_wishlist(String.t(), non_neg_integer()) :: [map()] def search_wishlist(query, limit \\ @pagination[:search_preview_limit]) do Wishlist.search_records(query, limit: limit) end @doc """ Searches artists by name. Searches across artist names in the artist_records table, returning distinct artists that match the query. """ @spec search_artists(String.t(), non_neg_integer()) :: [map()] def search_artists(query, limit \\ @pagination[:search_preview_limit]) do Artists.search_by_name(query, limit) end @doc """ Gets the count of search results for each category. Returns a map with counts for each category: - :collection_count - :wishlist_count - :artists_count """ @spec search_counts(String.t()) :: map() def search_counts(query) do %{ collection_count: Collection.search_records_count(query), wishlist_count: Wishlist.search_records_count(query), artists_count: search_artists_count(query), record_sets_count: RecordSets.count_record_sets(query) } end @doc """ Searches record sets by name, description, and contained records. """ @spec search_record_sets(String.t(), non_neg_integer()) :: [map()] def search_record_sets(query, limit \\ @pagination[:search_preview_limit]) do RecordSets.search_record_sets(query, limit: limit) end @doc """ Gets the count of artists matching the search query. """ @spec search_artists_count(String.t()) :: non_neg_integer() def search_artists_count(query) do Artists.search_by_name_count(query) end end