import logging
from typing import Dict, Optional
from uuid import uuid4

from django.conf import settings
from django.db import models
from django.utils.translation import gettext_lazy as _
from django_extensions.db.models import TimeStampedModel

from vrobbler.apps.scrobbles.mixins import ScrobblableMixin

logger = logging.getLogger(__name__)
BNULL = {"blank": True, "null": True}


class Producer(TimeStampedModel):
    name = models.CharField(max_length=255)
    uuid = models.UUIDField(default=uuid4, editable=False, **BNULL)

    def __str__(self):
        return f"{self.name}"


class Podcast(TimeStampedModel):
    name = models.CharField(max_length=255)
    uuid = models.UUIDField(default=uuid4, editable=False, **BNULL)
    producer = models.ForeignKey(
        Producer, on_delete=models.DO_NOTHING, **BNULL
    )
    active = models.BooleanField(default=True)
    url = models.URLField(**BNULL)

    def __str__(self):
        return f"{self.name}"


class Episode(ScrobblableMixin):
    COMPLETION_PERCENT = getattr(settings, 'PODCAST_COMPLETION_PERCENT', 90)

    podcast = models.ForeignKey(Podcast, on_delete=models.DO_NOTHING)
    number = models.IntegerField(**BNULL)
    pub_date = models.DateField(**BNULL)
    mopidy_uri = models.CharField(max_length=255, **BNULL)

    def __str__(self):
        return f"{self.title}"

    @classmethod
    def find_or_create(
        cls, podcast_dict: Dict, producer_dict: Dict, episode_dict: Dict
    ) -> Optional["Episode"]:
        """Given a data dict from Mopidy, finds or creates a podcast and
        producer before saving the epsiode so it can be scrobbled.

        """
        if not podcast_dict.get('name'):
            logger.warning(f"No name from source for podcast, not scrobbling")
            return

        producer = None
        if producer_dict.get('name'):
            producer, producer_created = Producer.objects.get_or_create(
                **producer_dict
            )
            if producer_created:
                logger.debug(f"Created new producer {producer}")
            else:
                logger.debug(f"Found producer {producer}")

        if producer:
            podcast_dict["producer_id"] = producer.id
        podcast, podcast_created = Podcast.objects.get_or_create(
            **podcast_dict
        )
        if podcast_created:
            logger.debug(f"Created new podcast {podcast}")
        else:
            logger.debug(f"Found podcast {podcast}")

        episode_dict['podcast_id'] = podcast.id

        episode, created = cls.objects.get_or_create(**episode_dict)
        if created:
            logger.debug(f"Created new episode: {episode}")
        else:
            logger.debug(f"Found episode {episode}")

        return episode
