from datetime import date, datetime, timedelta
import requests
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.mail import EmailMultiAlternatives
from django.utils.decorators import method_decorator
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import exceptions, status
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin, UpdateModelMixin
from rest_framework.permissions import AllowAny
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.status import HTTP_200_OK, HTTP_400_BAD_REQUEST
from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet
from verify_trusted.utils import send_cancel_email

from verify_trusted.companies.api.serializers import CompanySerializer
from verify_trusted.companies.models import Company, Subscription
from verify_trusted.users.api.serializers import (
    ContactSerializer,
    UserSerializer,
    UserUpdateSerializer,
    AddShopifyUrlSerializer,
    LogoutShopifyUrlSerializer,
    GetUserByShopifySerializer,
    PurchasePlanSerializer,
)
from verify_trusted.users.api.serializers.change_password import (
    ChangePasswordSerializer,
)
from verify_trusted.users.models import *
from verify_trusted.companies.models import *

User = get_user_model()


@method_decorator(
    name='list',
    decorator=swagger_auto_schema(
        responses={
            HTTP_200_OK: openapi.Response('Current user details', UserSerializer)
        }
    ),
)
class CurrentUserViewSet(
    ListModelMixin,
    UpdateModelMixin,
    GenericViewSet,
):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get_serializer_class(self):
        if self.action in ['companies', 'companies_v1']:
            return CompanySerializer
        if self.action == 'change_password':
            return ChangePasswordSerializer
        if self.action in ['update', 'partial_update']:
            return UserUpdateSerializer
        return super().get_serializer_class()

    def get_object(self):
        if self.action in ['list', 'change_password']:
            return self.request.user
        return super().get_object()

    def list(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        company = Company.objects.filter(user_id=instance.id).first()
        response_data = serializer.data
        if company is not None:
            response_data['company'] = company.id
        if len(response_data['companies']) > 0:
            response_data['companies'][0]['is_trial'] = False
            response_data['companies'][0]['due_date'] = None
            if response_data['companies'][0]['is_verified']:
                subscription = Subscription.objects.filter(
                    company=response_data['companies'][0]['id']
                ).first()
                if subscription is not None:
                    response_data['companies'][0]['is_expire'] = subscription.due_date <= date.today()
                    response_data['companies'][0]['is_trial'] = subscription.payment is None
                    response_data['companies'][0]['due_date'] = subscription.due_date
        return Response(response_data)

    @action(detail=False, methods=['GET'])
    def companies(self, request: Request, *args, **kwargs):
        user: User = request.user
        company = user.companies.first()
        if not company:
            return Response(None)
        serializer = self.get_serializer(company)
        response_data = serializer.data
        if (
            company.logo
            and hasattr(company.logo, 'name')
            and 'http' in company.logo.name
        ):
            response_data['logo'] = company.logo.name
        if len(response_data) > 0:
            response_data['is_expire'] = True
            response_data['is_trial'] = False
            response_data['due_date'] = None
            if response_data['is_verified']:
                subscription = Subscription.objects.filter(
                    company=response_data['id']
                ).first()
                if subscription is not None:
                    response_data['is_expire'] = subscription.due_date <= date.today()
                    response_data['is_trial'] = subscription.payment is None
                    response_data['due_date'] = subscription.due_date
        return Response(response_data)

    @action(detail=False, methods=['GET'], url_path='companies-v1')
    def companies_v1(self, request: Request, *args, **kwargs):
        user: User = request.user
        company = user.companies.first()
        if not company:
            return Response([])
        serializer = self.get_serializer(company)
        response_data = serializer.data
        if (
            company.logo
            and hasattr(company.logo, 'name')
            and 'http' in company.logo.name
        ):
            response_data['logo'] = company.logo.name
        if len(response_data) > 0:
            response_data['is_expire'] = True
            response_data['is_trial'] = False
            response_data['due_date'] = None
            if response_data['is_verified']:
                subscription = Subscription.objects.filter(
                    company=response_data['id']
                ).first()
                if subscription is not None:
                    response_data['is_expire'] = subscription.due_date <= date.today()
                    response_data['is_trial'] = subscription.payment is None
                    response_data['due_date'] = subscription.due_date
        return Response([response_data])

    # TODO: Update profile API

    # def perform_update(self, serializer):
    #     super().perform_update(serializer)
    # if 'email' in serializer.validated_data:
    #     send_activation_email(serializer.validated_data['email'])

    # TODO: Change password API
    @action(detail=False, methods=['POST'])
    def change_password(self, request, *args, **kwargs):
        self.object = self.get_object()
        serializer = self.get_serializer(data=request.data)

        if serializer.is_valid():
            if not self.object.check_password(
                serializer.validated_data['old_password']
            ):
                raise exceptions.ValidationError({'old_password': "MSG019"})
            self.object.set_password(serializer.validated_data['new_password'])
            self.object.save()
            response = {
                'message': 'MSG000',
            }

            return Response(response)
        return Response(serializer.errors, status=HTTP_400_BAD_REQUEST)

    # Deactive user
    @action(detail=False, methods=['POST'])
    def deactive(self, request, *args, **kwargs):
        user = self.request.user
        company = Company.objects.filter(user_id=user.id).first()
        if company is not None:
            company.user = None
            company.is_verified = False
            company.save()
        user.is_active = False
        user.save()
        send_cancel_email(user.email, company.url)
        return Response({'success': "Successful deactive"})


class ContactViewSet(APIView):
    serializer_class = ContactSerializer
    permission_classes = [AllowAny]

    def post(self, request):
        serializer = ContactSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        if settings.IS_PRODUCTION:
            send_to_email = [
                'info@verifytrusted.com',
                'verifytrusted.support@sphinxjsc.com',
                'admin@verifytrusted.com',
                'doanthanh58863@gmail.com'
            ]
        else:
            send_to_email = settings.DEFAULT_SEND_TO_EMAIL
        msg = EmailMultiAlternatives(
            # title:
            f"[Contact] {serializer.validated_data['name']} - {serializer.validated_data['email']}",
            # message:
            f"Date: {datetime.now()}\nName: {serializer.validated_data['name']}\nEmcount_user_signed_up_setail: {serializer.validated_data['email']}\nWebsite: {serializer.validated_data['website']}\nMessage: {serializer.validated_data['message']}",  # noqa
            # from:
            settings.DEFAULT_FROM_EMAIL,
            # to:
            send_to_email,
        )
        msg.send()
        return Response({'email': 'Successfully activated'}, status=status.HTTP_200_OK)


contact_view = ContactViewSet.as_view()

class AddTokenWithShopify(APIView):
    serializer_class = AddShopifyUrlSerializer
    permission_classes = [AllowAny]

    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        connect_token = serializer.validated_data.get('connect_token')
        shopify_url = serializer.validated_data.get('shopify_url')
        shopify_token = serializer.validated_data.get('shopify_token')
        if connect_token:
            profile = Profile.objects.filter(connect_token=connect_token).first()
            if profile:
                profile.shopify_url = shopify_url
                profile.shopify_token = shopify_token
                profile.save()
            else:
                return Response({'code':400,'message': 'This token is invalid'})
        return Response({'code':200,'message': 'Request processed successfully'})

shopify_url_view = AddTokenWithShopify.as_view()

class CheckUserShopify(APIView):
    serializer_class = GetUserByShopifySerializer
    permission_classes = [AllowAny]

    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        shopify_url = serializer.validated_data.get('shopify_url')
        
        if shopify_url:
            profile = Profile.objects.filter(shopify_url=shopify_url).first()
            if profile:
                user = profile.user
                serializer = UserSerializer(user)
                return Response({'code':200,'data':serializer.data})
        
        return Response({'code':400,'message': 'User not found'})
    

check_shopify_url_view = CheckUserShopify.as_view()


class LogoutShopify(APIView):
    serializer_class = LogoutShopifyUrlSerializer
    permission_classes = [AllowAny]

    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        connect_token = serializer.validated_data.get('connect_token')
        shopify_url = serializer.validated_data.get('shopify_url')
        if connect_token:
            profile = Profile.objects.filter(connect_token=connect_token,shopify_url=shopify_url).first()
            if profile:
                profile.shopify_url = None
                profile.save()
            else:
                return Response({'code':400,'message': 'Request processed failed'})
        return Response({'code':200,'message': 'Request processed successfully'})

logout_shopify_url_view = LogoutShopify.as_view()


class PurchasePlan(APIView):
    serializer_class = PurchasePlanSerializer
    permission_classes = [AllowAny]

    def post(self, request):
        serializer = self.serializer_class(data=request.data)
        serializer.is_valid(raise_exception=True)
        
        plan_id = serializer.validated_data.get('plan_id')
        company_id = serializer.validated_data.get('company_id')
        charge_id = serializer.validated_data.get('charge_id')
        plan = Plan.objects.filter(id=plan_id).first()
        company = Company.objects.filter(id=company_id).first()
        if not plan:
            return Response({'code':400,'message': 'No plan found'})
        if not company:
            return Response({'code':400,'message': 'No company found'})

        # try:
        #     with transaction.atomic():
        #         payment = Payment.objects.create(company=company, plan=plan)
        #         Subscription.objects.create(company=company, payment=payment, due_date=date.today() + timedelta(days=7))
        # except IntegrityError:
        #     return Response({'message': 'Subscription already exists'}, status=status.HTTP_400_BAD_REQUEST)

        payment = Payment.objects.create(company=company,plan=plan)
        if payment:
            subscription_obj = Subscription.objects.filter(company=company).update( payment=payment,due_date=date.today() + timedelta(days=30))
            profile = Profile.objects.filter(user=company.user).update(charge_id=charge_id)
        else:
            return Response({'code':400,'message': 'Something went wrong'})
        return Response({'code':200,'message': 'Request processed successfully'})

purchase_plan_url_view = PurchasePlan.as_view()


class RecurringPlan(APIView):
    permission_classes = [AllowAny]
    def get(self, request):
        users = Profile.objects.filter(active=True)
        # all_data = []
        for user in users:
            if user.shopify_url:
                charge_id = user.charge_id
                shopify_url = user.shopify_url
                shopify_api_url =f"https://{shopify_url}/admin/api/2023-04/recurring_application_charges/{charge_id}.json"
                headers = {'X-Shopify-Access-Token': user.shopify_token}
                response = requests.get(shopify_api_url, headers=headers)
                if response.status_code == 200:
                    data = response.json()
                    payment_status = data['recurring_application_charge']['status']
                    if payment_status == "active":
                        activated_on = data['recurring_application_charge']['activated_on']
                        activated_on = datetime.strptime(activated_on, "%Y-%m-%d").date()
                        company = Company.objects.filter(user=user.user).first()
                        subscription_obj = Subscription.objects.filter(company=company).update(due_date=activated_on + timedelta(days=30))
                    # all_data.append(data)
                else:
                    pass
        return Response({'message': 'Shopify API access completed for eligible users.'})
    
recurring_plan_url_view = RecurringPlan.as_view()