from django.db import models
from django.contrib.auth.models import User
from random import choice
from .album import Album
from .artist import Artist
from .vote import Vote
from playlist.spotify import spt
#from playlist.utils import track_from_json
import re

class TrackManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(old=False)

    def from_json(self, cls, json):
        try:
            return cls.objects.get(pk=json["id"])
        except cls.DoesNotExist:
            keys = [f.name for f in cls._meta.get_fields()]
            subset = {key:json[key] for key in set(keys) & set(json.keys())}
            return cls.objects.create(**subset)

    def track_from_json(self, json):
        """Creates the track, album and artist from spotify response."""
        # Album artists
        album_artists = []
        for artist in json["album"]["artists"]:
            album_artists.append(self.from_json(Artist, artist))
        del json["album"]["artists"]

        # Album
        album = self.from_json(Album, json["album"])
        album.image_url = json["album"]["images"][0]["url"]
        album.save()
        del json["album"]
        for artist in album_artists:
            album.artists.add(artist)

        # Track artists
        track_artists = []
        for artist in json["artists"]:
            track_artists.append(self.from_json(Artist, artist))
        del json["artists"]

        # Track
        track = self.from_json(Track, json)
        for artist in track_artists:
            track.artists.add(artist)
        track.album = album
        track.save()
        return track

    def create_from_spotify(self, spotify_link, profile):
        if re.match(r"^https:\/\/spotify.link.*", spotify_link):
            spotify_link = spt.unshort(spotify_link)

        m = re.match(r"^https:\/\/open.spotify.com\/track\/([a-zA-Z0-9]+)\??", spotify_link)
        if m is None:
            return None, Exception("Invalid Spotify track URL")

        spotify_id = m.group(1)

        try:
            existing_track = self.model.all_tracks.get(pk=spotify_id)
            if existing_track.old:
                existing_track.old = False
                existing_track.user = profile.user
                existing_track.save()
                return (existing_track, "Updated old track")
            else:
                return (None, "Track already exists")
        except:
           pass
        try:
            json = spt.get_song_info(spotify_id)
        except Exception as e:
            print(e)
            return (None, "Error fetching track")
            #return TemplateResponse(request, "Nominate.html", {"message_type": "error", "message": "Fout bij het ophalen van het liedje."})

        track = self.track_from_json(json)
        track.nominated_by = profile.user
        track.save()
        dup = track.is_duplicate_of()
        if dup:
            track.delete()
            return (None, "Track already exists")
        #get_banter.delay(track.id)
        profile.quota -= 1
        profile.save()
        return (track, None)

class Track(models.Model):
    def __str__(self):
        s = f"'{self.name}'"
        if self.artists.count() > 0:
            artists = list(map(lambda a:a.name, self.artists.all()))
            s += " door "
            s += " & ".join(artists)
        return s
    @property
    def artist(self):
        if self.artists.count() > 0:
            artists = list(map(lambda a:a.name, self.artists.all()))
            return " & ".join(artists)

    @property
    def name_sanitized(self):
        return re.match("[^\-\(]*\w", self.name)[0]

    @property
    def link(self):
        return f'https://open.spotify.com/track/{self.id}'

    @property
    def score(self):
        return Vote.objects.filter(track=self.id).aggregate(rating=models.Avg("points"))["rating"]

    def is_duplicate_of(self):
        tracks = Track.objects.exclude(id=self.id).filter(name__startswith=self.name_sanitized)
        artists = [artist.name for artist in self.artists.all()]
        for artist in artists:
            tracks = tracks.filter(artists__name__exact=artist)
        return tracks.first()


    id = models.CharField(primary_key=True, max_length=128)
    nominated_by = models.ForeignKey(User, blank=True, null=True, default=None, on_delete=models.SET_NULL)
    name = models.CharField(max_length=255)
    artists = models.ManyToManyField(Artist)
    album = models.ForeignKey(Album, blank=True, null=True, on_delete=models.SET_NULL)

    explicit = models.BooleanField(default=False)
    duration_ms = models.PositiveIntegerField(blank=True, null=True)
    popularity = models.PositiveIntegerField(blank=True, null=True)

    banter = models.TextField(null=True, blank=True)
    banter_done = models.BooleanField(default=False)

    old = models.BooleanField(default=False)
    from_playlist = models.CharField(max_length=255, null=True, blank=True, default=None)

    objects = TrackManager()
    all_tracks = models.Manager()
