"""Wishlist resolution and removal helpers.""" from __future__ import annotations from typing import Any, Dict, List from core.imports.context import ( get_import_original_search, get_import_search_result, get_import_source, get_import_source_ids, get_import_track_info, ) from core.wishlist.service import get_wishlist_service from database.music_database import get_database from utils.logging_config import get_logger logger = get_logger("wishlist.resolution") def _primary_track_artist_name(track_info: Dict[str, Any]) -> str: artists = (track_info or {}).get("artists", []) if isinstance(artists, list) and artists: first = artists[0] if isinstance(first, dict): return str(first.get("name", "") or "") return str(first or "") if isinstance(artists, str): return artists return str((track_info or {}).get("artist", "") or "") def _all_profile_wishlist_tracks(wishlist_service, database=None) -> List[Dict[str, Any]]: database = database or get_database() all_profiles = database.get_all_profiles() wishlist_tracks: List[Dict[str, Any]] = [] for profile in all_profiles: wishlist_tracks.extend(wishlist_service.get_wishlist_tracks_for_download(profile_id=profile["id"])) return wishlist_tracks def check_and_remove_from_wishlist(context: Dict[str, Any], wishlist_service=None, database=None) -> None: """Check whether a successful download should be removed from the wishlist.""" try: wishlist_service = wishlist_service or get_wishlist_service() source = get_import_source(context) source_ids = get_import_source_ids(context) source_label = { "spotify": "Spotify", "itunes": "iTunes", "deezer": "Deezer", "discogs": "Discogs", "hydrabase": "Hydrabase", }.get(source, "Source") track_info = get_import_track_info(context) or get_import_search_result(context) search_result = get_import_original_search(context) or get_import_search_result(context) track_id = None track_id = source_ids.get("track_id") or None if track_id: logger.info("[Wishlist] Found %s track ID from source_ids: %s", source_label, track_id) elif "wishlist_id" in track_info: wishlist_id = track_info["wishlist_id"] logger.info("[Wishlist] Found wishlist_id in context: %s", wishlist_id) wishlist_tracks = _all_profile_wishlist_tracks(wishlist_service, database=database) for wishlist_track in wishlist_tracks: if wishlist_track.get("wishlist_id") == wishlist_id: track_id = wishlist_track.get("track_id") or wishlist_track.get("spotify_track_id") or wishlist_track.get("id") logger.info("[Wishlist] Found track ID from wishlist entry: %s", track_id) break if not track_id: track_name = track_info.get("name") or search_result.get("title", "") artist_name = _primary_track_artist_name(track_info) or _primary_track_artist_name(search_result) if track_name and artist_name: logger.warning( "[Wishlist] No track ID found, checking for fuzzy match: '%s' by '%s'", track_name, artist_name, ) wishlist_tracks = _all_profile_wishlist_tracks(wishlist_service, database=database) for wishlist_track in wishlist_tracks: wl_name = wishlist_track.get("name", "").lower() wl_artists = wishlist_track.get("artists", []) wl_artist_name = "" if wl_artists: if isinstance(wl_artists[0], dict): wl_artist_name = wl_artists[0].get("name", "").lower() else: wl_artist_name = str(wl_artists[0]).lower() if wl_name == track_name.lower() and wl_artist_name == artist_name.lower(): track_id = wishlist_track.get("track_id") or wishlist_track.get("spotify_track_id") or wishlist_track.get("id") logger.info("[Wishlist] Found fuzzy match - track ID: %s", track_id) break if track_id: logger.info("[Wishlist] Attempting to remove track from wishlist: %s", track_id) removed = wishlist_service.mark_track_download_result(track_id, success=True) if removed: logger.info("[Wishlist] Successfully removed track from wishlist: %s", track_id) else: logger.warning("ℹ️ [Wishlist] Track not found in wishlist or already removed: %s", track_id) else: logger.warning("ℹ️ [Wishlist] No track ID found for wishlist removal check") except Exception as exc: logger.error("[Wishlist] Error in wishlist removal check: %s", exc) def check_and_remove_track_from_wishlist_by_metadata( track_data: Dict[str, Any], wishlist_service=None, database=None, ) -> bool: """Remove a wishlist track by metadata after a database/library match.""" try: wishlist_service = wishlist_service or get_wishlist_service() track_name = track_data.get("name", "") track_id = track_data.get("id", "") artists = track_data.get("artists", []) logger.info("[Analysis] Checking if track should be removed from wishlist: '%s' (ID: %s)", track_name, track_id) if track_id: removed = wishlist_service.mark_track_download_result(track_id, success=True) if removed: logger.info("[Analysis] Removed track from wishlist via direct ID match: %s", track_id) return True if track_name and artists: primary_artist = _primary_track_artist_name(track_data) if primary_artist: logger.warning( "[Analysis] No direct ID match, trying fuzzy match: '%s' by '%s'", track_name, primary_artist, ) wishlist_tracks = _all_profile_wishlist_tracks(wishlist_service, database=database) for wishlist_track in wishlist_tracks: wl_name = wishlist_track.get("name", "").lower() wl_artists = wishlist_track.get("artists", []) wl_artist_name = "" if wl_artists: if isinstance(wl_artists[0], dict): wl_artist_name = wl_artists[0].get("name", "").lower() else: wl_artist_name = str(wl_artists[0]).lower() if wl_name == track_name.lower() and wl_artist_name == primary_artist.lower(): spotify_track_id = ( wishlist_track.get("track_id") or wishlist_track.get("spotify_track_id") or wishlist_track.get("id") ) if spotify_track_id: removed = wishlist_service.mark_track_download_result(spotify_track_id, success=True) if removed: logger.info("[Analysis] Removed track from wishlist via fuzzy match: %s", spotify_track_id) return True logger.warning("ℹ️ [Analysis] Track not found in wishlist or already removed: '%s'", track_name) return False except Exception as e: logger.error("[Analysis] Error checking wishlist removal by metadata: %s", e) import traceback traceback.print_exc() return False __all__ = ["check_and_remove_from_wishlist", "check_and_remove_track_from_wishlist_by_metadata"]