# -*- encoding: utf-8 -*-

import logging

from django_filters import rest_framework as rest_filters
from rest_framework import permissions, filters, generics
from rest_framework.pagination import PageNumberPagination
from rest_framework.authentication import SessionAuthentication, TokenAuthentication
from rest_framework.parsers import MultiPartParser, FormParser

from apps.home.models import (
    Server,
    ContentFilter,
    MessageMutator,
    MessageStyle,
    Subscription,
    Content,
    UniqueContentRule
)
from apps.authentication.models import DiscordUser, ServerMember
from .metadata import ExpandedMetadata
from .serializers import (
    ServerSerializer,
    ContentFilterSerializer,
    MessageMutatorSerializer,
    MessageStyleSerializer,
    SubscriptionSerializer,
    ContentSerializer,
    UniqueContentRuleSerializer
)
from .permissions import HasServerAccess
from .errors import NotAMemberError

log = logging.getLogger(__name__)


class DefaultPagination(PageNumberPagination):
    """Default class for pagination in API views."""

    page_size = 10
    page_size_query_param = "page_size"
    max_page_size = 25


def is_automated_admin(user):
    return user.user_type == DiscordUser.USER_TYPES.AUTOMATED_USER and user.is_superuser


class ListView(generics.ListAPIView):
    authentication_classes = [SessionAuthentication, TokenAuthentication]
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = DefaultPagination
    metadata_class = ExpandedMetadata
    filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]


class ListCreateView(generics.ListCreateAPIView):
    authentication_classes = [SessionAuthentication, TokenAuthentication]
    permission_classes = [permissions.IsAuthenticated]
    pagination_class = DefaultPagination
    metadata_class = ExpandedMetadata
    filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]


class DetailView(generics.RetrieveAPIView):
    authentication_classes = [SessionAuthentication, TokenAuthentication]
    permission_classes = [permissions.IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser]


class ChangableDetailView(generics.RetrieveUpdateDestroyAPIView):
    authentication_classes = [SessionAuthentication, TokenAuthentication]
    permission_classes = [permissions.IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser]


class DeletableDetailView(generics.RetrieveDestroyAPIView):
    authentication_classes = [SessionAuthentication, TokenAuthentication]
    permission_classes = [permissions.IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser]


# region Servers

class Server_ListView(ListView):
    filterset_fields = ("id", "name", "icon_hash", "active")
    search_fields = ("name")
    ordering_fields = ("id", "name", "active")
    serializer_class = ServerSerializer

    def get_queryset(self):
        servers = ServerMember.objects.filter(user=self.request.user).values_list("server", flat=True)
        return Server.objects.filter(id__in=servers).order_by("id")


class Server_DetailView(DetailView):
    serializer_class = ServerSerializer

    def get_queryset(self):
        servers = ServerMember.objects.filter(user=self.request.user).values_list("server", flat=True)
        return Server.objects.filter(id__in=servers)


# region Filters

class ContentFilter_ListView(ListCreateView):
    filterset_fields = ("id", "server", "name", "match", "matching_algorithm", "is_insensitive", "is_whitelist")
    search_fields = ("name", "match")
    ordering_fields = ("id", "server", "name", "match", "matching_algorithm", "is_insensitive", "is_whitelist")
    serializer_class = ContentFilterSerializer

    def get_queryset(self):
        servers = ServerMember.objects.filter(user=self.request.user).values_list("server", flat=True)
        return ContentFilter.objects.filter(server__in=servers).order_by("name")


class ContentFilter_DetailView(ChangableDetailView):
    serializer_class = ContentFilterSerializer

    def get_queryset(self):
        servers = ServerMember.objects.filter(user=self.request.user).values_list("server", flat=True)
        return ContentFilter.objects.filter(server__in=servers)


# region Mutators

class MessageMutator_ListView(ListView):  # instances of this one are pre-defined ONLY
    filterset_fields = ("id", "name", "value")
    search_fields = ("name", "value")
    ordering_fields = ("id", "name", "value")
    serializer_class = MessageMutatorSerializer

    def get_queryset(self):
        return MessageMutator.objects.all()


class MessageMutator_DetailView(DetailView):
    serializer_class = MessageMutatorSerializer

    def get_queryset(self):
        return MessageMutator.objects.all()


# Message Styles

class MessageStyle_ListView(ListCreateView):
    filterset_fields = ("id", "server", "name", "is_embed", "is_hyperlinked", "show_author", "show_timestamp", "show_images", "fetch_images", "title_mutator", "description_mutator")
    search_fields = ("name",)
    ordering_fields = ("id", "server", "name", "is_embed", "is_hyperlinked", "show_author", "show_timestamp", "show_images", "fetch_images")
    serializer_class = MessageStyleSerializer

    def get_queryset(self):
        return MessageStyle.objects.all()


class MessageStyle_DetailView(ChangableDetailView):
    serializer_class = MessageStyleSerializer

    def get_queryset(self):
        return MessageStyle.objects.all()


# region Subscriptions

class Subscription_ListView(ListCreateView):
    filterset_fields = ("id", "server", "name", "url", "created_at", "updated_at", "extra_notes", "active", "publish_threshold", "filters", "message_style", "unique_rules")
    search_fields = ("name", "url", "extra_notes")
    ordering_fields = ("id", "server", "name", "url", "created_at", "updated_at", "extra_notes", "active", "message_style")
    serializer_class = SubscriptionSerializer

    def get_queryset(self):
        servers = ServerMember.objects.filter(user=self.request.user).values_list("server", flat=True)
        return Subscription.objects.filter(server__in=servers)


class Subscription_DetailView(ChangableDetailView):
    serializer_class = SubscriptionSerializer

    def get_queryset(self):
        servers = ServerMember.objects.filter(user=self.request.user).values_list("server", flat=True)
        return Subscription.objects.filter(server__in=servers)


# region Content

class Content_ListView(ListCreateView):
    filterset_fields = ("id", "subscription", "subscription__server", "item_id", "item_guid", "item_url", "item_title", "item_content_hash")
    search_fields = ("item_id", "item_guid", "item_url", "item_title", "item_content_hash")
    ordering_fields = ("id", "subscription", "item_id", "item_guid", "item_url", "item_title", "item_content_hash")
    serializer_class = ContentSerializer

    def get_queryset(self):
        servers = ServerMember.objects.filter(user=self.request.user).values_list("server", flat=True)
        subscriptions = Subscription.objects.filter(server__in=servers).values_list("id", flat=True)
        return Content.objects.filter(subscription__in=subscriptions).order_by("-subscription__created_at", "id")


class Content_DetailView(ChangableDetailView):
    serializer_class = ContentSerializer

    def get_queryset(self):
        servers = ServerMember.objects.filter(user=self.request.user).values_list("server", flat=True)
        subscriptions = Subscription.objects.filter(server__in=servers).values_list("id", flat=True)
        return Content.objects.filter(subscription__in=subscriptions).order_by("-subscription__created_at", "id")


# region Unique Rules

class UniqueContentRule_ListView(ListCreateView):
    filterset_fields = ("id", "name", "value")
    search_fields = ("name", "value")
    ordering_fields = ("id", "name", "value")
    serializer_class = UniqueContentRuleSerializer

    def get_queryset(self):
        return UniqueContentRule.objects.all()


class UniqueContentRule_DetailView(ChangableDetailView):
    serializer_class = UniqueContentRuleSerializer

    def get_queryset(self):
        return UniqueContentRule.objects.all()
