import sys
import types
from types import SimpleNamespace

# Stub optional Spotify dependency so metadata_service can import in tests.
if 'spotipy' not in sys.modules:
    spotipy = types.ModuleType('spotipy')
    oauth2 = types.ModuleType('spotipy.oauth2')

    class _DummySpotify:
        pass

    class _DummyOAuth:
        pass

    spotipy.Spotify = _DummySpotify
    oauth2.SpotifyOAuth = _DummyOAuth
    oauth2.SpotifyClientCredentials = _DummyOAuth
    spotipy.oauth2 = oauth2
    sys.modules['spotipy'] = spotipy
    sys.modules['spotipy.oauth2'] = oauth2

if 'config.settings' not in sys.modules:
    config_mod = types.ModuleType('config')
    settings_mod = types.ModuleType('config.settings')

    class _DummyConfigManager:
        def get(self, key, default=None):
            return default

        def get_active_media_server(self):
            return "plex"

    settings_mod.config_manager = _DummyConfigManager()
    config_mod.settings = settings_mod
    sys.modules['config'] = config_mod
    sys.modules['config.settings'] = settings_mod

from core.repair_jobs import track_number_repair as tnr


class _FakeSearchClient:
    def __init__(self, search_results=None):
        self.search_results = search_results or []
        self.search_calls = []

    def search_albums(self, query, limit=10):
        self.search_calls.append((query, limit))
        return self.search_results


def _make_context():
    return SimpleNamespace(db=None, mb_client=None)


def test_resolve_album_tracklist_prefers_primary_source_album_id(monkeypatch):
    context = _make_context()
    file_track_data = [('/music/test.flac', '01 - Track.flac', None)]
    cache = {'album_tracks_cache': {}, 'title_similarity': 0.8}
    calls = []

    monkeypatch.setattr(tnr, 'get_primary_source', lambda: 'deezer')
    monkeypatch.setattr(
        tnr,
        '_lookup_album_ids_from_db',
        lambda *_args, **_kwargs: {'spotify': 'sp-album', 'itunes': 'it-album', 'deezer': 'dz-album'},
    )
    monkeypatch.setattr(tnr, '_read_album_id_from_file', lambda *_args, **_kwargs: (None, None))
    monkeypatch.setattr(tnr, '_read_spotify_track_id_from_file', lambda *_args, **_kwargs: None)
    monkeypatch.setattr(tnr, '_read_musicbrainz_album_id_from_file', lambda *_args, **_kwargs: None)
    monkeypatch.setattr(tnr, '_read_album_artist_from_file', lambda *_args, **_kwargs: (None, None))

    def fake_get_album_tracks_for_source(source, album_id):
        calls.append((source, album_id))
        return {'items': [{'name': f'{source} track', 'track_number': 1, 'disc_number': 1}]}

    monkeypatch.setattr(tnr, 'get_album_tracks_for_source', fake_get_album_tracks_for_source)

    result = tnr.TrackNumberRepairJob()._resolve_album_tracklist(file_track_data, '/music', context, cache)

    assert result is not None
    assert result[0]['name'] == 'deezer track'
    assert calls == [('deezer', 'dz-album')]


def test_resolve_album_tracklist_uses_source_priority_for_search(monkeypatch):
    context = _make_context()
    file_track_data = [('/music/test.flac', 'Track.flac', None)]
    cache = {'album_tracks_cache': {}, 'title_similarity': 0.8}
    track_calls = []

    discogs_client = _FakeSearchClient([SimpleNamespace(id='dg-album')])
    spotify_client = _FakeSearchClient([SimpleNamespace(id='sp-album')])

    monkeypatch.setattr(tnr, 'get_primary_source', lambda: 'discogs')
    monkeypatch.setattr(tnr, '_lookup_album_ids_from_db', lambda *_args, **_kwargs: {})
    monkeypatch.setattr(tnr, '_read_album_id_from_file', lambda *_args, **_kwargs: (None, None))
    monkeypatch.setattr(tnr, '_read_spotify_track_id_from_file', lambda *_args, **_kwargs: None)
    monkeypatch.setattr(tnr, '_read_musicbrainz_album_id_from_file', lambda *_args, **_kwargs: None)
    monkeypatch.setattr(tnr, '_read_album_artist_from_file', lambda *_args, **_kwargs: ('Album Title', 'Artist Name'))
    monkeypatch.setattr(
        tnr,
        'get_client_for_source',
        lambda source: {'discogs': discogs_client, 'spotify': spotify_client}.get(source),
    )

    def fake_get_album_tracks_for_source(source, album_id):
        track_calls.append((source, album_id))
        return {'items': [{'name': f'{source} track', 'track_number': 1, 'disc_number': 1}]}

    monkeypatch.setattr(tnr, 'get_album_tracks_for_source', fake_get_album_tracks_for_source)

    result = tnr.TrackNumberRepairJob()._resolve_album_tracklist(file_track_data, '/music', context, cache)

    assert result is not None
    assert result[0]['name'] == 'discogs track'
    assert discogs_client.search_calls == [('Artist Name Album Title', 5)]
    assert spotify_client.search_calls == []
    assert track_calls == [('discogs', 'dg-album')]
