import random
from datetime import date

from django.conf import settings
from django.forms.models import model_to_dict
from django.shortcuts import render
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet

from verify_trusted.companies.models import Company, Review, Subscription
from verify_trusted.widgets.models import Seal, Widget
from ...companies.api.serializers import CompanySerializer

from ...reviews.models import Platform
from .serializers import SealSerializer, WidgetSerializer


class WidgetViewSet(ModelViewSet):
    serializer_class = WidgetSerializer
    queryset = Widget.objects.all()
    permission_classes = [IsAuthenticatedOrReadOnly]

    @staticmethod
    def get_template_light(layout_id):
        switcher = {
            4: 'slider-light.html',
            16: 'grid-light.html',
        }
        return switcher.get(layout_id, 'list-light.html')

    @staticmethod
    def get_template_dark(layout_id):
        switcher = {
            4: 'slider-dark.html',
            16: 'grid-dark.html',
        }
        return switcher.get(layout_id, 'list-dark.html')

    def create(self, request, *args, **kwargs):
        old_widget = Widget.objects.filter(company_id=self.request.data['company'])
        if len(old_widget) > 0:
            return Response({'widget': 'Cannot create more than 1 widget'})
        return super().create(request, *args, **kwargs)

    def retrieve(self, request: Request, *args, **kwargs):
        instance = self.get_object()
        template_name = (
            self.get_template_light(instance.layout_id)
            if instance.set_id == 'light-background'
            else self.get_template_dark(instance.layout_id)
        )
        number_of_review = (
            instance.number_of_review if instance.number_of_review is not None else 5
        )
        reviews = instance.reviews.filter(
            source__platform__status=Platform.Status.ACTIVE, is_active=True
        )
        # if len(reviews) < 1:
        #     reviews = Review.objects.filter(
        #         source__company=instance.company,
        #         source__platform__status=Platform.Status.ACTIVE,
        #         is_active=True,
        #     )
        if instance.order_by == Widget.OrderBy.RANDOM:
            random_items = list(reviews.order_by('display_order'))
            number_of_review = min(number_of_review, len(random_items))
            reviews = random.sample(random_items, number_of_review)[:number_of_review]
        elif instance.order_by == Widget.OrderBy.NEWER:
            reviews = list(reviews.order_by('-id', 'display_order')[:number_of_review])
        else:
            reviews = list(
                reviews.order_by('-rating', 'display_order')[:number_of_review]
            )
        company_id = instance.company.id
        get_company = (
            Company.objects.with_reviews_count().filter(id=company_id)
                .first()
        )
        company = CompanySerializer(get_company).data
        review_count = 0
        top_average_rating = 0
        if company['review_sources'] is not None:
            for review_source in company['review_sources']:
                source_platform = review_source['platform']
                if source_platform['status'] in [Platform.Status.ACTIVE, Platform.Status.HIDE_REVIEWS]:
                    if 'reviews_count' in review_source.keys() and review_source['reviews_count'] is not None:
                        review_count += review_source['reviews_count']
                if 'average_rating' in review_source.keys() and review_source[
                    'average_rating'] is not None and top_average_rating < review_source['average_rating']:
                    top_average_rating = review_source['average_rating']
        company['reviews_count'] = review_count
        # top_average_rating = instance.company.review_sources.order_by('-average_rating').first().average_rating
        subscription = Subscription.objects.filter(company_id=company_id).first()
        is_visibility = False
        if subscription is not None:
            is_visibility = bool(
                instance.company.is_verified and subscription.due_date >= date.today()
            )

        return render(
            request,
            template_name,
            context={
                'reviews_data': instance,
                'reviews': reviews,
                'company': company,
                'client_name': settings.CLIENT_NAME,
                'static_url': settings.AWS_S3_CUSTOM_DOMAIN,
                'is_visibility': is_visibility,
                'average_rating': top_average_rating
            },
        )

    def get_widget(self, request: Request, *args, **kwargs):
        queryset = super().get_queryset()
        company_id = self.kwargs['company_id']
        serializer = WidgetSerializer(queryset.filter(company_id=company_id), many=True)
        data = serializer.data[0]
        data_review= data['reviews']
        filter_data = [d for d in data_review if d['source']['platform']['status'] in [Platform.Status.ACTIVE]]
        serializer.data[0]['reviews'] = filter_data
        return Response(serializer.data)

    def demo(self, request: Request, *args, **kwargs):
        company_id = self.kwargs['company_id']
        reviews = Review.objects.filter(
            source__company_id=company_id,
            source__platform__status=Platform.Status.ACTIVE,
            is_active=True,
        ).order_by('-rating')[:5]
        get_company = (
            Company.objects.with_reviews_count()
                .with_avg_rating()
                .filter(id=company_id)
                .first()
        )
        company = CompanySerializer(get_company).data
        reviews_data = []
        for review in reviews:
            data = model_to_dict(review)
            if not review.source.platform.logo:
                data['platform'] = None
            else:
                data['platform'] = review.source.platform.logo.url
                data['platform_name'] = review.source.platform.name
            reviews_data.append(data)
        review_count = 0
        average_rating = 0
        ratings = []
        if company['review_sources'] is not None:
            for review_source in company['review_sources']:
                if review_source['reviews_count'] is not None and review_source['platform'] is not None:
                    source_platform = review_source['platform']
                    if source_platform['status'] in [Platform.Status.ACTIVE, Platform.Status.HIDE_REVIEWS]:
                        review_count += review_source['reviews_count']
                        ratings.append(review_source['average_rating'])

        if len(ratings) > 0:
            average_rating = sum(ratings) / len(ratings)
        elif len(reviews_data) > 0:
            review_count = len(reviews_data)
            average_rating = sum([i['rating'] for i in reviews_data]) / len(reviews_data)
        response_data = {
            'company': {
                'reviews_count': review_count,
                'average_rating': average_rating,
            },
            'reviews': reviews_data,
        }
        return Response(response_data)


class SealViewSet(ModelViewSet):
    serializer_class = SealSerializer
    queryset = Seal.objects.all()
    permission_classes = [IsAuthenticatedOrReadOnly]

    def retrieve(self, request: Request, *args, **kwargs):
        instance = self.get_object()
        '''
        TODO:
         - Checking due_date is None?
         - Checking if due_date exceeded?
        '''
        is_visibility = False
        subscription = Subscription.objects.filter(company=instance.company).first()
        if subscription is not None:
            is_visibility = bool(
                instance.company.is_verified and subscription.due_date >= date.today()
            )

        template_name = 'seal_template.html'
        return render(
            request,
            template_name,
            context={
                'is_visibility': is_visibility,
                'seal_type': instance.seal_type,
                'url': instance.company.url,
                'client_name': settings.CLIENT_NAME,
                'static_url': settings.AWS_S3_CUSTOM_DOMAIN,
            },
        )

    def get_seal(self, request: Request, *args, **kwargs):
        queryset = super().get_queryset()
        company_id = self.kwargs['company_id']
        serializer = SealSerializer(
            queryset.filter(company_id=company_id).order_by('-id').first()
        )
        return Response(serializer.data)
