from datetime import date, timedelta
from urllib.parse import urlparse

from django.contrib.auth import get_user_model
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from verify_trusted.companies.history_types import HistoryType
from verify_trusted.companies.models import (
    Company,
    Payment,
    Plan,
    Review,
    Social,
    SourceSocial,
    Subscription,
)
from verify_trusted.reviews.api.serializers import (
    PlatformSerializer,
    ReviewSourceSerializer,
)
from verify_trusted.utils.serializers import (
    AverageRatingRep,
    DynamicFieldsModelSerializer,
    ReviewsCountRep,
)
from verify_trusted.widgets.models import Widget

User = get_user_model()


class SourceSocialSerializer(serializers.ModelSerializer):
    class Meta:
        model = SourceSocial
        fields = '__all__'


class SocialSerializer(serializers.ModelSerializer):
    class Meta:
        model = Social
        fields = '__all__'


# TODO: Split to seperated Create/Update/Retrieve Serializer
class CompanySerializer(
    ReviewsCountRep,
    AverageRatingRep,
    DynamicFieldsModelSerializer,
):
    user = serializers.PrimaryKeyRelatedField(
        required=False, read_only=False, queryset=User.objects.all()
    )
    socials = SocialSerializer(many=True, required=False)
    average_rating = serializers.FloatField(
        max_value=5.0, allow_null=True, required=False, default=None
    )
    review_sources = ReviewSourceSerializer(
        read_only=True,
        many=True,
    )

    class Meta:
        model = Company
        exclude = (
            'crawled_at',
            'last_review_date',
            'last_synced_at',
            'accreditation',
            'search_vector',
        )
        extra_kwargs = {
            'name': {
                'allow_blank': False,
                'required': True,
                'error_messages': {
                    'blank': 'MSG004',
                },
            },
            'url_display': {
                'allow_blank': False,
                'required': True,
                'error_messages': {
                    'blank': 'MSG0018',
                },
            },
        }

    def create(self, validated_data):
        socials = validated_data.pop('socials', None)
        validated_data['ssl_status'] = (
            True if 'ssl_status' not in validated_data else validated_data['ssl_status']
        )
        validated_data['one_year'] = (
            True if 'one_year' not in validated_data else validated_data['one_year']
        )
        if 'category_main' not in validated_data:
            validated_data['category_main'] = 'Others'
        # Handle logo
        if 'request' in self.context and self.context['request'].FILES:
            logo_data = self.context['request'].FILES.getlist('file')[0]
            validated_data['logo'] = logo_data
        if 'map' in validated_data and 'currency_symbol' not in validated_data:
            for data in validated_data['map']['address_components']:
                if 'country' in data['types'] and data['short_name'] == 'GB':
                    # validated_data['currency_symbol'] = 'GBP'
                    break
        # if (
        #     'country_code' in validated_data
        #     and 'currency_symbol' not in validated_data
        #     and validated_data['country_code'] == 'GB'
        # ):
        #     validated_data['currency_symbol'] = 'GBP'
        company = super().create(validated_data)
        if socials is not None:
            for data in socials:
                data['company'] = company.id
                data['source'] = data['source'].id
                social_serializer = SocialSerializer(data=data)
                if social_serializer.is_valid():
                    social_serializer.create(social_serializer.validated_data)
        subscription_serializer = SubscriptionSerializer(
            data={
                'company': company.id,
                'due_date': date.today() + timedelta(days=7),
            }
        )
        subscription_serializer.is_valid(raise_exception=True)
        subscription_serializer.create(subscription_serializer.validated_data)
        self.create_widget(company)
        return company

    def update(self, instance: Company, validated_data):
        if 'user' in validated_data:
            if validated_data['user'] != instance.user:
                # https://django-simple-history.readthedocs.io/en/latest/historical_model.html#change-reason
                instance._change_reason = HistoryType.CLAIMED
                validated_data['is_verified'] = True
                subscription = Subscription.objects.filter(company=instance.id).first()
                if subscription is None:
                    subscription_serializer = SubscriptionSerializer(
                        data={
                            'company': instance.id,
                            'due_date': date.today() + timedelta(days=7),
                        }
                    )
                    subscription_serializer.is_valid(raise_exception=True)
                    subscription_serializer.create(
                        subscription_serializer.validated_data
                    )
                self.create_widget(instance)
            elif validated_data['user'] is None:
                validated_data['is_verified'] = False
        socials = validated_data.pop('socials', None)
        if socials is not None and isinstance(socials, list):
            # Clear current `socials`
            instance.socials.all().delete()
            # Recreate Company's socials
            s = [
                Social(url=social['url'], company=instance, source=social['source'])
                for social in socials
            ]

            Social.objects.bulk_create(s)
        # Handle logo
        if self.context['request'].FILES:
            logo_data = self.context['request'].FILES.getlist('file')[0]
            validated_data['logo'] = logo_data
        if 'map' in validated_data and 'currency_symbol' not in validated_data:
            for data in validated_data['map']['address_components']:
                if 'country' in data['types'] and data['short_name'] == 'GB':
                    # validated_data['currency_symbol'] = 'GBP'
                    break
        # if (
        #     'country_code' in validated_data
        #     and 'currency_symbol' not in validated_data
        #     and validated_data['country_code'] == 'GB'
        # ):
        #     validated_data['currency_symbol'] = 'GBP'
        return super().update(instance, validated_data)

    def validate_url_display(self, data):  # noqa
        if '//' not in data:
            data = '%s%s' % ('https://', data)
        try:
            o = urlparse(data)
        except ValueError as e:
            raise ValidationError('MSG014') from e
        if not o.hostname:
            raise ValidationError('MSG014')
        url_existed = Company.objects.filter(url=data).exists()
        if self.instance and url_existed or not self.instance and url_existed:
            raise ValidationError('MSG036')
        return data

    def validate(self, attrs):
        if 'url_display' in attrs:
            url_display = attrs['url_display']
            base_url = '%s%s' % ('', attrs['url_display'])
            if '//' not in url_display:
                url_display = '%s%s' % ('https://', url_display)
                attrs['url_display'] = url_display
            attrs['url'] = urlparse(url_display).hostname + urlparse(url_display).path
            # urlparse(url_display).hostname
        if 'user' in attrs and attrs['user'] is not None:
            attrs['is_verified'] = True
        if 'average_rating' in attrs.keys() and attrs['average_rating'] is None:
            attrs['average_rating'] = 0
        return super().validate(attrs)

    def create_widget(self, company: Company):
        if company is not None:
            old_widget = Widget.objects.filter(company_id=company.id).first()
            if old_widget is None:
                widget_data = {
                    "company": company,
                    "layout_id": 4,
                    "layout_type": "Slider",
                    "more_style": {
                        "backgroundColor": "#FFFFFF",
                        "borderColor": "#DBDFEA",
                        "dateFontSize": 12,
                        "nameColor": "#3D424D",
                        "nameFontSize": 15,
                        "reviewColor": "#3D424D",
                        "reviewFontSize": 14,
                    },
                    "number_of_review": 0,
                    "order_by": "TOP_RATING",
                    "set_id": "light-background",
                }
                widget = Widget.objects.create(**widget_data)
                widget.save()


class CompanyUpdateSerializer(CompanySerializer):
    url_display = serializers.CharField(
        required=False,
    )


class CompanyFirstLetterSerializer(serializers.ModelSerializer):
    class Meta:
        model = Company
        fields = (
            'id',
            'name',
            'url',
            'url_display',
        )


class CompanyUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ["id", "username", "email", "name", 'is_superuser']


class CompanyListSerializer(CompanySerializer):
    user = CompanyUserSerializer()

    class Meta:
        model = Company
        exclude = CompanySerializer.Meta.exclude


class CompanyRemoveUserSerializer(CompanySerializer):
    class Meta:
        model = Company
        fields = ['user']


class CompanyAllCategorySerializer(CompanySerializer):
    class Meta:
        model = Company
        fields = ['category_main']


class CompanyExportExcelSerializer(CompanySerializer):
    class Meta:
        model = Company
        # fields = ['id']
        fields = ['id', 'name', 'url', 'email', 'url_display', 'address']


class ReviewSerializer(serializers.ModelSerializer):
    # TODO: Source serializer
    platform = PlatformSerializer(
        fields=['name', 'logo'],
        read_only=True,
        required=False,
        source='source.platform',
    )

    class Meta:
        model = Review
        exclude = ('external_id',)


# class UpdateReviewSerializer(serializers.ModelSerializer):
#     # TODO: Source serializer
#
#     class Meta:
#         model = Review
#         exclude = ()
class PlanSerializer(serializers.ModelSerializer):
    class Meta:
        model = Plan
        fields = '__all__'

class SubscriptionCompanySerializer(serializers.Serializer):
    company_id = serializers.PrimaryKeyRelatedField(required=True, queryset=Company.objects.all())
    due_date = serializers.DateField(required=True)


class CompanyPaymentSerializer(CompanySerializer):
    user = CompanyUserSerializer()

    class Meta:
        model = Company
        fields = ('id', 'name', 'user', 'map', 'phone', 'address')


class PaymentCompanySerializer(serializers.ModelSerializer):
    plan = PlanSerializer()
    company = CompanyPaymentSerializer(many=False)

    class Meta:
        model = Payment
        fields = '__all__'


class PaymentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Payment
        exclude = ('status', 'stripe_status', 'stripe_url', 'stripe_id')


class PaymentExportSerializer(serializers.ModelSerializer):
    class Meta:
        model = Payment
        fields = '__all__'


class PaymentUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Payment
        fields = ('description', 'currency', 'address', 'country')


class PaymentListSerializer(serializers.ModelSerializer):
    plan = PlanSerializer()
    company = CompanyPaymentSerializer()

    class Meta:
        model = Payment
        fields = '__all__'


class SubscriptionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Subscription
        fields = '__all__'
