from django.http import HttpResponse

from core.musiq.music_provider import SongProvider, PlaylistProvider
from core.models import ArchivedSong, Setting
from mopidy_spotify.web import OAuthClient

from urllib.parse import urlparse

from core.models import ArchivedSong, ArchivedPlaylist

_web_client = None
def get_web_client():
    global _web_client
    if _web_client is None:
        client_id = Setting.objects.get(key='spotify_client_id').value
        client_secret = Setting.objects.get(key='spotify_client_secret').value
        _web_client = OAuthClient(
            base_url="https://api.spotify.com/v1",
            refresh_url="https://auth.mopidy.com/spotify/token",
            client_id=client_id,
            client_secret=client_secret)
    return _web_client

class SpotifySongProvider(SongProvider):
    @staticmethod
    def get_id_from_external_url(url):
        return urlparse(url).path.split('/')[-1]

    @staticmethod
    def get_id_from_internal_url(url):
        return url.split(':')[-1]

    def __init__(self, musiq, query, key):
        super().__init__(musiq, query, key)
        self.type = 'spotify'
        self.spotify_library = musiq.player.player.library
        self.metadata = dict()
        self.web_client = get_web_client()

    def check_cached(self):
        if self.query is not None and self.query.startswith('https://open.spotify.com/'):
            extracted_id = SpotifySongProvider.get_id_from_external_url(self.query)
            if extracted_id is not None:
                self.id = extracted_id

        if not self._check_cached():
            return False
        # Spotify songs cannot be cached and have to be streamed everytime
        return False

    def check_downloadable(self):
        if self.id is None:
            results = self.spotify_library.search({'any': [self.query]})

            try:
                track_info = results[0].tracks[0]
            except AttributeError:
                self.error = 'Song not found'
                return False
            self.id = SpotifySongProvider.get_id_from_internal_url(track_info.uri)
            self.gather_metadata(track_info=track_info)
        else:
            self.gather_metadata()

        return True

    def download(self, ip, background=True, archive=True, manually_requested=True):
        self.enqueue(ip, archive=archive, manually_requested=manually_requested)
        # spotify need to be streamed, no download possible
        return True

    def gather_metadata(self, track_info=None):
        if not track_info:
            results = self.spotify_library.search({'uri': [self.get_internal_url()]})
            track_info = results[0].tracks[0]

        self.metadata['internal_url'] = track_info.uri
        self.metadata['external_url'] = self.get_external_url()
        self.metadata['artist'] = track_info.artists[0].name
        self.metadata['title'] = track_info.name
        self.metadata['duration'] = track_info.length / 1000

    def get_metadata(self):
        if not self.metadata:
            self.gather_metadata()
        return self.metadata

    def get_internal_url(self):
        return 'spotify:track:' + self.id

    def get_external_url(self):
        return 'https://open.spotify.com/track/' + self.id

    def get_suggestion(self):
        result = self.web_client.get(
            'recommendations',
            params={
                'limit': '1',
                'market': 'from_token',
                'seed_tracks': self.id,
            },
        )

        try:
            external_url = result['tracks'][0]['external_urls']['spotify']
        except IndexError:
            self.error = 'no recommendation found'
            return None

        return external_url

    def request_radio(self, ip):
        result = self.web_client.get(
            'recommendations',
            params={
                'limit': self.musiq.base.settings.max_playlist_items,
                'market': 'from_token',
                'seed_tracks': self.id,
            },
        )

        for track in result['tracks']:
            external_url = track['external_urls']['spotify']
            self.musiq._request_music('', external_url, None, False, 'spotify', archive=False, manually_requested=False)

        return HttpResponse('queueing radio')

class SpotifyPlaylistProvider(PlaylistProvider):

    @staticmethod
    def get_id_from_external_url(url):
        if not url.startswith('spotify:playlist:'):
            return None
        return urlparse(url).path.split('/')[-1]

    def __init__(self, musiq, query, key):
        super().__init__(musiq, query, key)
        self.type = 'spotify'
        self.web_client = get_web_client()

    def search_id(self):
        result = self.web_client.get(
            "search",
            params={
                'q': self.query,
                'limit': '1',
                'market': 'from_token',
                'type': 'playlist',
            },
        )

        try:
            list_info = result['playlists']['items'][0]
        except IndexError:
            self.error = 'No playlist found'
            return None

        list_id = list_info['id']
        self.title = list_info['name']

        return list_id

    def is_radio(self):
        return False

    def fetch_metadata(self):
        # download at most 50 tracks for a playlist (spotifys maximum)
        # for more tracks paging would need to be implemented
        result = self.web_client.get(
            f"playlists/{self.id}/tracks",
            params={
                'fields': 'items(track(external_urls(spotify)))',
                'limit': '50',
                'market': 'from_token',
            },
        )

        track_infos = result['items']
        for track_info in track_infos:
            self.urls.append(track_info['track']['external_urls']['spotify'])