from django.db.models import Prefetch
from rest_framework import mixins, viewsets

from config import plugins
from funkwhale_api.activity import record
from funkwhale_api.common import fields, permissions
from funkwhale_api.federation import routes
from funkwhale_api.music import utils as music_utils
from funkwhale_api.music.models import Track
from funkwhale_api.users.oauth import permissions as oauth_permissions

from . import filters, models, serializers


class ListeningViewSet(
    mixins.CreateModelMixin,
    mixins.ListModelMixin,
    mixins.RetrieveModelMixin,
    viewsets.GenericViewSet,
):
    serializer_class = serializers.ListeningSerializer
    queryset = models.Listening.objects.all().select_related("actor__attachment_icon")

    permission_classes = [
        oauth_permissions.ScopePermission,
        permissions.OwnerPermission,
    ]
    required_scope = "listenings"
    anonymous_policy = "setting"
    owner_checks = ["write"]
    owner_field = "actor.user"
    filterset_class = filters.ListeningFilter

    def get_serializer_class(self):
        if self.request.method.lower() in ["head", "get", "options"]:
            return serializers.ListeningSerializer
        return serializers.ListeningWriteSerializer

    def perform_create(self, serializer):
        r = super().perform_create(serializer)
        instance = serializer.instance
        plugins.trigger_hook(
            plugins.LISTENING_CREATED,
            listening=instance,
            confs=plugins.get_confs(self.request.user),
        )
        routes.outbox.dispatch(
            {"type": "Listen", "object": {"type": "Track"}},
            context={
                "track": instance.track,
                "actor": instance.actor,
                "id": instance.fid,
            },
        )
        record.send(serializer.instance)
        return r

    def get_queryset(self):
        queryset = super().get_queryset()
        queryset = queryset.filter(
            fields.privacy_level_query(
                self.request.user, "actor__user__privacy_level", "actor__user"
            )
        )
        tracks = (
            Track.objects.with_playable_uploads(
                music_utils.get_actor_from_request(self.request)
            )
            .prefetch_related(
                "artist_credit",
                "album__artist_credit__artist",
                "artist_credit__artist__attachment_cover",
            )
            .select_related("attributed_to")
        )
        return queryset.prefetch_related(Prefetch("track", queryset=tracks))

    def get_serializer_context(self):
        context = super().get_serializer_context()
        context["user"] = self.request.user
        return context
