from email import message
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import *
from .functions import *
import random
from datetime import datetime, timedelta
from django.conf import settings
from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from rest_framework_simplejwt.tokens import RefreshToken
from passlib.hash import django_pbkdf2_sha256 as handler
from django.template.loader import render_to_string
from django.core import mail
from django.core.mail import EmailMultiAlternatives
import math, random, pytz, string
from django.contrib import messages
from . import forms
from admin_panel.models import *
import json
from .authentication import authenticated
from .serializers import *
from django.core.files.storage import FileSystemStorage
import os
from admin_panel.common_functions import *
from admin_panel.functions import TransferToConnectedAccount
from seer_user.serializers import SeerUserSerializer, FortunerTellerReviewSerializer
from admin_panel.serializers import ContentSerializer, FAQSerializer
from pyfcm import FCMNotification
from django.views.generic import TemplateView
import stripe
from rest_framework import generics
from twilio.rest import Client
# Create your views here.

# twillio
account_sid= settings.TWILIO_ACCOUNT_SID
auth_token = settings.TWILIO_AUTH_TOKEN
client = Client(account_sid, auth_token)
from_mobile_number = settings.TWILIO_MOBILE_NUMBER

def uploadTheProfile(image):

	fullPath='media/fortuneteller_profile'
	fs = FileSystemStorage(location=fullPath)
	fullPath2='/media/fortuneteller_profile'
	filetype = os.path.splitext(image.name)[1]
	theName=randomStringFunctionForImage()
	theImageName=str(theName)+str(filetype)
	filename = fs.save(theImageName, image)
	return str(fullPath2)+'/'+filename



def generateTranscationsIdFortune():
	lastObj= FortuneTellerTranscations.objects.all().last()
	if lastObj:
		if not lastObj.transcation_id:
			return 'TRANS000001'

		theId=lastObj.transcation_id
		theId=theId[5:]
		theId=int(theId)+1
		theId=str(theId)
		theId=theId.zfill(5)
		return "TRANS"+str(theId)
	else:
		return 'TRANS000001'
	
def generateTranscationsId():
	lastObj= SeerUserTranscation.objects.all().last()
	if lastObj:
		if not lastObj.transcation_id:
			return 'TRANS000001'

		theId=lastObj.transcation_id
		theId=theId[5:]
		theId=int(theId)+1
		theId=str(theId)
		theId=theId.zfill(5)
		return "TRANS"+str(theId)
	else:
		return 'TRANS000001'

def generatePayoutTranscationsId():
	lastObj= FortunePayoutTranscation.objects.all().last()
	if lastObj:
		if not lastObj.transcation_id:
			return 'PAYOUT000001'

		theId=lastObj.transcation_id
		theId=theId[6:]
		theId=int(theId)+1
		theId=str(theId)
		theId=theId.zfill(6)
		return "PAYOUT"+str(theId)
	else:
		return 'PAYOUT000001'

def generate_referral_code(length=8):
	characters = string.ascii_uppercase + string.ascii_lowercase + string.digits
	referral_code = ''.join(random.choice(characters) for _ in range(length))
	return 'FORTUNE'+referral_code

class Register(APIView):
	def post(self,request):
		try:
			data = request.data
			first_name = data.get('first_name')
			last_name = data.get('last_name')
			email = data.get('email')
			password = data.get('password')
			date_of_birth = data.get('date_of_birth')
			get_referal_code = data.get('get_referal_code')
			if not email:
				return Response({"message":'email is required'},status=status.HTTP_400_BAD_REQUEST)
			if not first_name:
				return Response({"message":'first_name is required'},status=status.HTTP_400_BAD_REQUEST)
			if not last_name:
				return Response({"message":'last_name is required'},status=status.HTTP_400_BAD_REQUEST)
			if not password:
				return Response({"message":'password is required'},status=status.HTTP_400_BAD_REQUEST)
			if not date_of_birth:
				return Response({"message":'date_of_birth is required'},status=status.HTTP_400_BAD_REQUEST)
			new_password = handler.hash(password)
			fortune_teller_obj = FortuneTeller.objects.filter(email=email).first()
			if fortune_teller_obj:
				return Response({"message":"The email is already registered"},status=status.HTTP_409_CONFLICT)
			else:
				if get_referal_code:
					check_code = FortuneTeller.objects.filter(referal_code=get_referal_code).first()
					if not check_code:
						return Response({"message":"Invalid referal code"},status=status.HTTP_409_CONFLICT)
				fortune_teller_obj = FortuneTeller.objects.create(first_name=first_name,last_name=last_name,email=email,date_of_birth=date_of_birth,password=new_password,referal_code=generate_referral_code())
				if get_referal_code:
					check_code = FortuneTeller.objects.filter(referal_code=get_referal_code).first()
					if check_code:
						referal_bonus = GeneralSettings.objects.all().first()
						FotuneTellerWallet.objects.create(fortune_teller=fortune_teller_obj,amount=referal_bonus.refer_friend_off)
						
						check_wallet = FotuneTellerWallet.objects.filter(fortune_teller = check_code).first()
						if check_wallet:
							new_amount = int(check_wallet.amount) + int(referal_bonus.refer_friend_off)
							check_wallet.amount = new_amount
							check_wallet.save()
						else:
							FotuneTellerWallet.objects.create(fortune_teller=check_code,amount=referal_bonus.refer_friend_off)

						FortuneTellerNotifications.objects.create(message="You have received your referal bonus successfully",notification_type="referal_bonus",fortune_teller=fortune_teller_obj)
				verify_token = RefreshToken.for_user(fortune_teller_obj)
				token = verify_token.access_token
				verify_link = '/fortune_teller/email-verify?token=' + str(token)
				complete_link = settings.BASE_URL+verify_link
				fortune_teller_obj.email_verification_link = token
				fortune_teller_obj.save()

				# # Time management
				# slots = [{"day":"Monday","is_active":"false","morning_opening":"","morning_closing":"",
		  		# 		"evening_opening":"","evening_closing":"","chat_price":"","video_price":"","session_time":""},
				# 		{"day":"Tuesday","is_active":"false","morning_opening":"","morning_closing":"",
	   			# 		"evening_opening":"","evening_closing":"","chat_price":"","video_price":"","session_time":""},
				# 		{"day":"Wednesday","is_active":"false","morning_opening":"","morning_closing":"",
				# 		"evening_opening":"","evening_closing":"","chat_price":"","video_price":"","session_time":""},
				# 		{"day":"Thursday","is_active":"false","morning_opening":"","morning_closing":"",
				# 		"evening_opening":"","evening_closing":"","chat_price":"","video_price":"","session_time":""},
				# 		{"day":"Friday","is_active":"false","morning_opening":"","morning_closing":"",
				# 		"evening_opening":"","evening_closing":"","chat_price":"","video_price":"","session_time":""},
				# 		{"day":"Saturday","is_active":"false","morning_opening":"","morning_closing":"",
				# 		"evening_opening":"","evening_closing":"","chat_price":"","video_price":"","session_time":""},
				# 		{"day":"Sunday","is_active":"false","morning_opening":"","morning_closing":"",
				# 		"evening_opening":"","evening_closing":"","chat_price":"","video_price":"","session_time":""}]
				# fortune_teller_time = FortuneTellerTiming.objects.create(fortune_teller=fortune_teller_obj,slots=slots)

				subject = "Verify Account"
				html_message = render_to_string('email_verifcation.html', {'link': complete_link})
				plain_message = html_message
				from_email = settings.EMAIL_HOST_USER
				to = email
				mail.send_mail(subject, plain_message, from_email, [to], html_message=html_message)
				AdminNotifications.objects.create(message=first_name+' '+last_name+' fortune teller has been succesfully registered with us.',type='fortune_teller_register')
			return Response({"message":'You have been successfully registered with us.Please verify your email.'})
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR) 


class SocialLogin(APIView):
	def post(self, request):
		try:
			data = request.data
			provider_id = data.get('provider_id')
			email = data.get('email')
			first_name = data.get('first_name')
			last_name = data.get('last_name')
			social_id = data.get('social_id')
			device_type = data.get('device_type')
			fcm_token = data.get('fcm_token')
			
			if not provider_id or not social_id:
				return Response({'message': 'Provider and social_id are required.'}, status=status.HTTP_400_BAD_REQUEST)
			if not first_name:
				return Response({'message': 'first_name is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not last_name:
				return Response({'message': 'last_name is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not email:
				return Response({'message': 'email is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not social_id:
				return Response({'message': 'email is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not device_type:
				return Response({'message': 'device_type is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not fcm_token:
				return Response({'message': 'fcm_token is required'}, status=status.HTTP_400_BAD_REQUEST)
			

			# Check if social account already exists in the database
	
			fortune_teller_obj = FortuneTeller.objects.filter(social_id=social_id).first()
			if fortune_teller_obj.account_deleted == 1:
				return Response({'message': 'This account has been deleted.For more information contact admin.'}, status=status.HTTP_400_BAD_REQUEST)

			if not fortune_teller_obj:
				# If social account not found, create a new one
				fortune_teller_obj = FortuneTeller.objects.create(first_name=first_name, last_name=last_name, social_id=social_id,
					  provider_id=provider_id,email=email,device_type=device_type,fcm_token=fcm_token,referal_code=generate_referral_code())
				# Additional logic for generating and sending OTP via email
				# OTP = GenerateOTP()
				# customerObj.otp = OTP
				# customerObj.save()
				# message = "\nOTP has been sent on you registered email successfully:\n" + OTP
				# context = {}
				# context['message'] = message
				# context['email'] = email
				# email_data = render_to_string('forgot-link.html', context)
				# to_emails = customerObj.email
				# subject = "Verify OTP:"
				# message = EmailMultiAlternatives(subject=subject, from_email=settings.EMAIL_HOST_USER, to=[to_emails], body=message)
				# message.attach_alternative(email_data, "text/html")
				# message.send(fail_silently=False)

			# Issue tokens (refresh token and access token) for the authenticated user
			refresh_token = RefreshToken.for_user(fortune_teller_obj)
			fortune_teller_obj.last_activity = datetime.now()
			fortune_teller_obj.save()
			allData={'id':fortune_teller_obj.id,
					'first_name':fortune_teller_obj.first_name,
					'last_name':fortune_teller_obj.last_name,
					'email':fortune_teller_obj.email,
					'date_of_birth':fortune_teller_obj.date_of_birth,
					'is_profile_completed':fortune_teller_obj.is_profile_completed,
					'is_stripe_account_connect':fortune_teller_obj.is_stripe_account_connect,
					'is_stripe_verified':fortune_teller_obj.is_stripe_verified,
					'refresh': str(refresh_token),
					'access': str(refresh_token.access_token),
				   }

			return Response({'message': 'Success', 'data': allData})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class LoginMobile(APIView):
	def post(self,request):
		try:
			data = request.data
			country_code = data.get('country_code') 
			phone_number = data.get('phone_number')
			fcm_token = data.get('fcm_token')
			device_type = data.get('device_type')
			the_otp=random.randrange(1000, 9999, 5)
			if not country_code:
				return Response({"message":'country_code is required'},status=status.HTTP_400_BAD_REQUEST)
			if not phone_number:
				return Response({"message":'phone_number is required'},status=status.HTTP_400_BAD_REQUEST)
			mobile_number = country_code + phone_number
			fortune_teller_obj = FortuneTeller.objects.filter(phone_number=mobile_number).first()
			
			if fortune_teller_obj:
				if fortune_teller_obj.account_deleted == 1:
					return Response({'message': 'This account has been deleted.For more information contact admin.'}, status=status.HTTP_400_BAD_REQUEST)


			if not fortune_teller_obj:
				fortune_teller_obj = FortuneTeller.objects.create(phone_number=mobile_number,referal_code=generate_referral_code())
			fortune_teller_obj.otp = the_otp
			fortune_teller_obj.fcm_token = fcm_token
			fortune_teller_obj.device_type  =device_type
			fortune_teller_obj.last_activity = datetime.now()
			fortune_teller_obj.save()
			# message = client.messages.create(
            #             body= 'Your SEER verification code is: '+str(the_otp),
            #             from_=from_mobile_number,
            #             to= mobile_number
            #         )
			userData = {
				'otp':fortune_teller_obj.otp,			
			}
			return Response({"message":'Success','data':userData})
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR) 


class emailVerification(APIView):
	def get(self,request):
		try:
			token = request.GET.get('token')
			fortune_Obj = FortuneTeller.objects.filter(email_verification_link = token).first()
			fortune_Obj.email_verified = True
			fortune_Obj.save()
			return render(request,'email_verification_success.html')
		except  Exception as e:
			return render(request,'email_verfication_failed.html')

	
class OtpVerification(APIView):
	def post(self,request):
		try:
			data=request.data
			country_code = data.get('country_code') 
			phone_number = data.get('phone_number')
			otp = data.get('otp')
			if not country_code:
				return Response({"message":'country_code is required'},status=status.HTTP_400_BAD_REQUEST)
			if not phone_number:
				return Response({"message":'phone_number is required'},status=status.HTTP_400_BAD_REQUEST)
			if not otp:
				return Response({"message":'otp is required'},status=status.HTTP_400_BAD_REQUEST)
			mobile_number = country_code + phone_number
			try:
				fortune_teller_obj = FortuneTeller.objects.get(phone_number=mobile_number,otp=otp)
			except Exception as e:
				return Response({"message":'Invalid otp','data':{}},status=status.HTTP_400_BAD_REQUEST)
			refresh_token = RefreshToken.for_user(fortune_teller_obj)
			allData={'id':fortune_teller_obj.id,
				'first_name':fortune_teller_obj.first_name,
				'last_name':fortune_teller_obj.last_name,
				'email':fortune_teller_obj.email,
				'date_of_birth':fortune_teller_obj.date_of_birth,
				'is_profile_completed':fortune_teller_obj.is_profile_completed,
				'is_stripe_account_connect':fortune_teller_obj.is_stripe_account_connect,
				'is_stripe_verified':fortune_teller_obj.is_stripe_verified,
				'refresh': str(refresh_token),
				'access': str(refresh_token.access_token),
				}
			return Response({"message":'Success','data':allData})
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR) 
		

class LoginUser(APIView):
	def post(self,request):
		try:
			data = request.data
			email = data.get('email')
			password = data.get('password')
			fcm_token = data.get('fcm_token')
			device_type = data.get('device_type')
			if not email:
				return Response({"message":'email is required'},status=status.HTTP_400_BAD_REQUEST) 
			if not password:
				return Response({"message":'password is required'},status=status.HTTP_400_BAD_REQUEST)  
			user  = FortuneTeller.objects.filter(email=email).count()
			if user == 0:
				return Response({"message":'This email does not exist in our database, please register'},status=status.HTTP_404_NOT_FOUND)
			fortuneObj  = FortuneTeller.objects.filter(email=email,status=True,end_date__isnull=True).first()
			if fortuneObj.account_deleted == 1:
				return Response({'message': 'This account has been deleted.For more information contact admin.'}, status=status.HTTP_400_BAD_REQUEST)


			if not fortuneObj:
				return Response({"message":'Your account has not been activated, Please contact to admin.'},status=status.HTTP_401_UNAUTHORIZED)
			check_password = fortuneObj.password
			check = handler.verify(password,check_password)
			if fortuneObj.email_verified == False:
				return Response({"message":'Please verify your email first'},status=status.HTTP_400_BAD_REQUEST)
			if check:
				fortuneObj.fcm_token = fcm_token
				fortuneObj.device_type  =device_type
				fortuneObj.last_activity = datetime.now()
				fortuneObj.save()
				refresh_token = RefreshToken.for_user(fortuneObj)
				allData={'id':fortuneObj.id,
					'first_name':fortuneObj.first_name,
					'last_name':fortuneObj.last_name,
					'email':fortuneObj.email,
					'date_of_birth':fortuneObj.date_of_birth,
					'is_profile_completed':fortuneObj.is_profile_completed,
					'is_stripe_account_connect':fortuneObj.is_stripe_account_connect,
					'is_stripe_verified':fortuneObj.is_stripe_verified,
					'refresh': str(refresh_token),
					'access': str(refresh_token.access_token),
				   }
				return Response({"message":'Login Successfully','data':allData})
			else:
				return Response({"message":'Invalid password'},status=status.HTTP_401_UNAUTHORIZED)
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class FortuneTellerForgetPassword(APIView):
	def post(self,request):
			try:
				data = request.data
				email = data.get('email')
				if not email:
					return Response({"message":'Email is required'})
				user  = FortuneTeller.objects.filter(email=email).count()
				if user == 0:
					return Response({"message":'This email does not exist in our database, please enter the valid email address.'},status=status.HTTP_404_NOT_FOUND)
				fortuneObj  = FortuneTeller.objects.filter(email=email).first()
				if fortuneObj:
					ran_num = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(12)])
					baselink =  '/fortune_teller/forgot/' + str(fortuneObj.email) + '/' + ran_num
					completelink = str(settings.BASE_URL) + baselink
					fortuneObj.forgot_password_link = baselink
					fortuneObj.save()
					subject = 'Forgot Password'
					html_message = render_to_string('forget_password_email.html', {'link': completelink})
					plain_message = html_message
					from_email = settings.EMAIL_HOST_USER
					to = email
					mail.send_mail(subject, plain_message, from_email, [to], html_message=html_message)
					return Response({"message":'Reset password link has been sent to this email address.'})
				else:
					return Response({"message":'Email not exists'})

			except Exception as e:
				print(e)
				return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class forgetPasswordVerification(APIView):
	def get(self,request):
		link = str(self.request.path)
		user_email = link.split('/')[-2]
		link_expiry = FortuneTeller.objects.filter(email = user_email).first()
		if link_expiry.forgot_password_link == "LinkExpiry":
			return render(request,'link-expire.html')
		fortune_obj = FortuneTeller.objects.filter(email = user_email, forgot_password_link = link).first()
		
		if fortune_obj:
			valid = True
		else:
			valid = False
		return render(request,'forgot.html',{'valid':valid})	

	def post(self,request):
		form = forms.forgetverification(request.POST)
		if form.is_valid():
			new_password = form.cleaned_data.get('new_password')
			confirm_new_password = form.cleaned_data.get('confirm_new_password')
			link = str(self.request.path)
			user_email = link.split('/')[-3]
			encrypt_password = handler.hash(new_password)
			fortune_obj = FortuneTeller.objects.filter(email = user_email).first()
			if fortune_obj:
				fortune_obj.password = encrypt_password
				fortune_obj.forgot_password_link = "LinkExpiry"
				fortune_obj.save()
				messages.success(request, "Changed successfully")
				return render(request,'password_success.html')
		else:
			return render(request, 'forgot.html', {'form': form})	
		
class getProfile(APIView):
	def get(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message':str(e)},status=status.HTTP_401_UNAUTHORIZED)
			fortune_Obj=FortuneTeller.objects.filter(id=uid).first()
			if not fortune_Obj:
				return Response({'message': 'user not found'}, status=status.HTTP_404_NOT_FOUND)
			allData=FortuneTellerSerializer(fortune_Obj).data
			review_obj = FortunetellerRatingReviews.objects.filter(fortune_teller=fortune_Obj)
			review_data = FortunerTellerReviewSerializer(review_obj,many=True).data
			return Response({'message':'Success','data':allData,'reviews':review_data})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

		
class getServices(APIView):
	def get(self, request):
		try:
			services = Service.objects.filter(status=True, end_date__isnull=True)
			serialized_services = ServiceSerializer(services, many=True).data
			return Response({'message': 'Success', 'data': serialized_services})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class getSkills(APIView):
	def get(self, request):
		try:
			skills = Skill.objects.filter(status=True, end_date__isnull=True)
			serialized_skills = SkillSerializer(skills, many=True).data
			return Response({'message': 'Success', 'data': serialized_skills})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class FortuneTellerCompleteProfile(APIView):
	def post(self, request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)

			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)

			data = request.data
			services = data.get('services')
			skills = data.get('skills')
			first_name = data.get('first_name')
			last_name = data.get('last_name')
			email = data.get('email')
			gender = data.get('gender')
			date_of_birth = data.get('date_of_birth')
			total_experience = data.get('total_experience')
			bio = data.get('bio')
			languages = data.get('languages')
			image = data.get('image')
			bank_details = data.get('bank_details')
			timezone = data.get('timezone')
			
			fortune_teller_obj = FortuneTeller.objects.filter(email=email).exclude(id=fortune_teller.id).first()
			if fortune_teller_obj:
				return Response({"message":"The email is already registered"},status=status.HTTP_409_CONFLICT)

			if not services:
				return Response({"message": 'services is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not skills:
				return Response({"message": 'skills is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not email:
				return Response({"message": 'email is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not gender:
				return Response({"message": 'gender is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not first_name:
				return Response({"message": 'first_name is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not last_name:
				return Response({"message": 'last_name is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not date_of_birth:
				return Response({"message": 'date_of_birth is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not total_experience:
				return Response({"message": 'total_experience is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not bio:
				return Response({"message": 'bio is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not languages:
				return Response({"message": 'languages is required'}, status=status.HTTP_400_BAD_REQUEST)
			# if not bank_details:
			# 	return Response({"message": 'bank_details is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not timezone:
				return Response({"message": 'timezone is required'}, status=status.HTTP_400_BAD_REQUEST)
			# for service_id in services.split(','):
			# 	service = Service.objects.filter(id=service_id).first()
			# 	if not service:
			# 		return Response({'message': f'Service with ID {service_id} not found'}, status=status.HTTP_404_NOT_FOUND)
			# 	FortuneTellerService.objects.create(fortune_teller=fortune_teller, service=service)

			# Get birthdate input from the user format: YYYY-MM-DD
			year, month, day = map(int, date_of_birth.split('-'))
			# Get the astrological sign
			horoscope = get_astrological_sign(day, month)
			# Get the chines Zodiac
			zodiac = get_chinese_zodiac(year)
			# Get the five element
			element = get_five_element(year)

			horoscope_obj = Horoscope.objects.filter(horoscope=horoscope).first()
			chinese_obj =  ChineseZodiac.objects.filter(chinese_zodiac=zodiac).first()
			elements_obj = FiveElements.objects.filter(element_name=element).first()
			sign_detail = FortuneTellerSignDetail.objects.create(fortune_teller=fortune_teller,horoscope=horoscope_obj,
						chinese_zodiac=chinese_obj,five_element=elements_obj)
			fortune_teller.first_name = first_name
			fortune_teller.last_name = last_name
			fortune_teller.date_of_birth = date_of_birth
			fortune_teller.email = email
			fortune_teller.gender = gender
			fortune_teller.services = services
			fortune_teller.skills = skills
			fortune_teller.total_experience = total_experience
			fortune_teller.bio = bio
			fortune_teller.languages = languages
			fortune_teller.is_profile_completed = True
			fortune_teller.bank_details = bank_details
			fortune_teller.timezone = timezone
			if image:
				fileUrl=uploadTheProfile(image)
				fortune_teller.image=str(fileUrl)
			fortune_teller.save()

			return Response({'message': 'Success'})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class FortuneTellerEditProfile(APIView):
	def post(self, request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)

			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)

			data = request.data
			services = data.get('services')
			skills = data.get('skills')
			first_name = data.get('first_name')
			last_name = data.get('last_name')
			total_experience = data.get('total_experience')
			bio = data.get('bio')
			languages = data.get('languages')
			image = data.get('image')
			bank_details = data.get('bank_details')
			print('image============',image)
			if not services:
				return Response({"message": 'services is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not skills:
				return Response({"message": 'skills is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not first_name:
				return Response({"message": 'first_name is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not last_name:
				return Response({"message": 'last_name is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not total_experience:
				return Response({"message": 'total_experience is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not bio:
				return Response({"message": 'bio is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not languages:
				return Response({"message": 'languages is required'}, status=status.HTTP_400_BAD_REQUEST)
			# if not bank_details:
			# 	return Response({"message": 'bank_details is required'}, status=status.HTTP_400_BAD_REQUEST)


			# for service_id in services.split(','):
			# 	service = Service.objects.filter(id=service_id).first()
			# 	if not service:
			# 		return Response({'message': f'Service with ID {service_id} not found'}, status=status.HTTP_404_NOT_FOUND)
			# 	fortune_services = FortuneTellerService.objects.filter(fortune_teller=fortune_teller, service=service).first()
			# 	if not fortune_services:
			# 		fortune_services = FortuneTellerService.objects.create(fortune_teller=fortune_teller, service=service)
			fortune_teller.first_name = first_name
			fortune_teller.last_name = last_name
			fortune_teller.services = services
			fortune_teller.skills = skills
			fortune_teller.total_experience = total_experience
			fortune_teller.bio = bio
			fortune_teller.languages = languages
			fortune_teller.bank_details = bank_details
			if image:
				# fileUrl=uploadTheProfile(image)
				fortune_teller.image=image
			fortune_teller.save()

			return Response({'message': 'Success'})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

def most_common(lst):
	return max(set(lst), key=lst.count)



class AddMbti(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)

			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			
			extraversion_introversion = str(request.data.get('extraversion_introversion'))
			print("extraversion_introversion",extraversion_introversion)
			if not extraversion_introversion:
				return Response({"message": 'extraversion_introversion is required'}, status=status.HTTP_400_BAD_REQUEST)
			first_pair_mbti = most_common(eval(extraversion_introversion))
			
			sensing_intuition = str(request.data.get('sensing_intuition'))
			print("sensing_intuition",sensing_intuition)

			if not sensing_intuition:
				return Response({"message": 'sensing_intuition is required'}, status=status.HTTP_400_BAD_REQUEST)
			second_pair_mbti = most_common(eval(sensing_intuition))

			thinking_feeling = str(request.data.get('thinking_feeling'))
			print("thinking_feeling",thinking_feeling)

			if not thinking_feeling:
				return Response({"message": 'thinking_feeling is required'}, status=status.HTTP_400_BAD_REQUEST)
			third_pair_mbti = most_common(eval(thinking_feeling))

			judging_perceiving = str(request.data.get('judging_perceiving'))
			print("judging_perceiving",judging_perceiving)

			if not judging_perceiving:
				return Response({"message": 'fourth array is required'}, status=status.HTTP_400_BAD_REQUEST)
			fourth_pair_mbti = most_common(eval(judging_perceiving))

			created_mbti = first_pair_mbti + second_pair_mbti + third_pair_mbti + fourth_pair_mbti
			fetch_mbti = MBTI.objects.filter(mbti_name = created_mbti,end_date__isnull = True).first()
			FortuneTellerSignDetail.objects.filter(fortune_teller = fortune_teller).update(mbti = fetch_mbti )
			return Response({'message': 'Success','data':f'You are {fetch_mbti.tagline}({created_mbti}) type!'})

		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class UploadImages(APIView):
	def post(self, request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)

			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)

			data = request.data
			images = data.getlist('images')
			image_urls = []

			for image in images:
				image_path = uploadTheProfile(image)
				# image_url = settings.BASE_URL + image_path 
				image_urls.append(image_path)
			# # image_urls_str = ','.join(image_urls)
			# if not seer_user_obj.images:
			# 	seer_user_obj.images = image_urls
			# 	seer_user_obj.primary_image = image_urls[0]
			# 	seer_user_obj.save()

			return Response({'message': 'Success','data':image_urls})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class FortuneTellerDeleteAccount(APIView):
	def get(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)

			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			fortune_teller.delete()
			AdminNotifications.objects.create(message=fortune_teller.first_name+' '+fortune_teller.last_name+' fortune teller has deleted their account.',type='fortune_teller_delete_account')

			return Response({'message': 'Account deleted successfully'})
		
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class GetFortunetellerFaq(APIView):
	def get(self,request):
		try:
			faq_obj = Faq.objects.filter(end_date__isnull =True,type="Fortuneteller").order_by('-id')
			all_data = FAQSerializer(faq_obj,many=True).data
			return Response({'message':'Success','data':all_data})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		
		

class GetFortunetellerBlog(APIView):
	def get(self,request):
		try:
			content_obj =  ContentManagement.objects.filter(page_type='Blog').first()
			allData=ContentSerializer(content_obj).data
			return Response({'message':'Success','data':allData})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		
class GetFortunetellerPrivacyPolicy(APIView):
	def get(self,request):
		try:
			content_obj =  ContentManagement.objects.filter(page_type='Privacy Policy',user_type='fortuneteller').first()
			allData=ContentSerializer(content_obj).data
			return Response({'message':'Success','data':allData})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class GetFortunetellerTerms(APIView):
	def get(self,request):
		try:
			content_obj =  ContentManagement.objects.filter(page_type='Terms & conditions',user_type='fortuneteller').first()
			allData=ContentSerializer(content_obj).data
			return Response({'message':'Success','data':allData})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class ResetPassword(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)

			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			data = request.data
			old_password = data.get('old_password')
			new_password = data.get('new_password')
			if not old_password:
				return Response({"message": 'old_password is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not new_password:
				return Response({"message": 'new_password is required'}, status=status.HTTP_400_BAD_REQUEST)
			check_password = fortune_teller.password
			check = handler.verify(old_password,check_password)
			new_password = handler.hash(new_password)
			if check:
				fortune_teller.password = new_password
				fortune_teller.save()
				return Response({'message': 'Success'})
			else:
				return Response({'message': 'The old password is incorrect'}, status=status.HTTP_403_FORBIDDEN)

		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class NotificationSettings(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'user not found'}, status=status.HTTP_404_NOT_FOUND)
		
			data = request.data
			notification_status = data.get('notification_status')
			if not notification_status:
				return Response({'message':'notification_status is required'},status=status.HTTP_400_BAD_REQUEST)
			fortune_teller.notification_status = notification_status
			fortune_teller.save()
		
			return Response({'message':'Success'})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		
class FortunetellerHelpSupport(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			data = request.data
			title = data.get('title')
			message = data.get('message')
			if not fortune_teller:
				return Response({'message': 'user not found'}, status=status.HTTP_404_NOT_FOUND)
			
			if not title:
				return Response({'message':'title is required'},status=status.HTTP_400_BAD_REQUEST)
			if not message:
				return Response({'message':'message is required'},status=status.HTTP_400_BAD_REQUEST)
			HelpSupport.objects.create(title=title,message=message,fortune_teller=fortune_teller)
			AdminNotifications.objects.create(message=fortune_teller.first_name+' '+fortune_teller.last_name+' fortune teller requested a help & support .',type='fortune_teller_help_support')

			return Response({'message':'Your request has been submitted successfully. We will revert you back sortly.'})
		except Exception as e:
		   return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR) 
		
class GetFortunetellerNotifications(APIView):
	def get(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'user not found'}, status=status.HTTP_404_NOT_FOUND)
			
			notification_obj = FortuneTellerNotifications.objects.filter(fortune_teller = fortune_teller,end_date__isnull = True).order_by('-id')
			all_data = FortuneNotificationSerializer(notification_obj,many=True).data
			return Response({'message':'Success','data':all_data})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class DeleteFortuneNotifications(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			notification_id = request.data.get('id')
			if not notification_id:
				return Response({'message':'id is required'},status=status.HTTP_400_BAD_REQUEST)
			FortuneTellerNotifications.objects.filter(id=notification_id).update(end_date=datetime.now())
			return Response({'message':'Success'})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class FortunetellerTimeSlots(APIView):
	def get(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()

			fortune_teller_time = FortuneTellerTiming.objects.filter(fortune_teller=fortune_teller).first()
			serialize_time = FortuneTimingSerializer(fortune_teller_time).data
			return Response({'message': 'Success', 'data': serialize_time})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			data = request.data
			slots = data.get('slots')
			if not slots:
				return Response({'message':'slots is required'},status=status.HTTP_400_BAD_REQUEST)
			fortune_teller_time = FortuneTellerTiming.objects.filter(fortune_teller=fortune_teller).first()
			if not fortune_teller_time:
				fortune_teller_time = FortuneTellerTiming.objects.create(fortune_teller=fortune_teller)

			fortune_teller_time.slots=slots
			fortune_teller_time.save()

			return Response({'message':'Success'})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class AppointmentRequestList(APIView):
	def get(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			appoint_obj = FortuneAppointmentBook.objects.filter(fortune_teller=fortune_teller,appointment_status='Pending',is_paid=True).order_by('-id')
			serialize_data = AppointmentRequestListSerializer(appoint_obj,many=True).data
			return Response({'message': 'Success', 'data': serialize_data})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)	
		
class AppointmentDetails(APIView):
	def get(self, request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)

			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			data = request.query_params
			appointment_id = data.get('appointment_id')

			if not appointment_id:
				return Response({'message': 'appointment id is required'}, status=status.HTTP_400_BAD_REQUEST)

			appoint_obj = FortuneAppointmentBook.objects.filter(fortune_teller=fortune_teller, id=appointment_id, appointment_status='Pending').first()

			if not appoint_obj:
				return Response({'message': 'Appointment not found'}, status=status.HTTP_404_NOT_FOUND)

			appointment_data = AppointmentRequestListSerializer(appoint_obj).data
			seer_user_obj = SeerUser.objects.filter(id=appoint_obj.seer_user.id).first()

			if not seer_user_obj:
				return Response({'message': 'user not found'}, status=status.HTTP_404_NOT_FOUND)

			user_data = SeerUserSerializer(seer_user_obj).data

			combined_data = {
				'user_data': user_data,
				'appointment_data': appointment_data
			}
			return Response({'message': 'Success', 'data': combined_data})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class AcceptOrDeclineAppointment(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message':str(e)},status=status.HTTP_401_UNAUTHORIZED)
			
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			data = request.data
			appointment_id = data.get('id')
			status_type = data.get('status_type')
			if not appointment_id:
				return Response({'message':'appointment id is required'},status=status.HTTP_400_BAD_REQUEST)
			if not status_type:
				return Response({'message':'status_type is required'},status=status.HTTP_400_BAD_REQUEST)
			if status_type == 'Accepted' or status_type == 'Declined':
				
				if status_type == "Accepted":
					appointment_obj = FortuneAppointmentBook.objects.filter(id=appointment_id,fortune_teller=fortune_teller).first()
					if not appointment_obj:
						return Response({'message': 'Appointment not found'}, status=status.HTTP_404_NOT_FOUND)
					appointment_obj.appointment_status = status_type
					appointment_obj.save()

					transaction_obj = SeerUserTranscation.objects.filter(booking=appointment_obj).first()
					if transaction_obj.charge_id:
						stripe.api_key = settings.STRIPE_SECRET_KEY
						stripe.Charge.capture(transaction_obj.charge_id)
					# wallet_obj = FotuneTellerWallet.objects.filter(fortune_teller=fortune_teller).first()
					# if wallet_obj:
					# 	wallet_obj.amount += appointment_obj.price
					# 	wallet_obj.save()
					# else:
					# 	FotuneTellerWallet.objects.create(fortune_teller=fortune_teller,amount=appointment_obj.price)

					# FortuneTellerTranscations.objects.create(transcation_id=generateTranscationsIdFortune(),seer_user=appointment_obj.seer_user,fortune_teller=appointment_obj.fortune_teller,amount=appointment_obj.price,payment_mode='wallet',transcation_type="appointment")
					seer_obj =  SeerUser.objects.filter(id=appointment_obj.seer_user.id).first()
					SeerUserNotifications.objects.create(message='Your appointment '+appointment_obj.appointment_id+' has been accepted successfully.',notification_type="appointment_booking",seer_user= seer_obj)
					
					if seer_obj.notification_status:
						registration_id = seer_obj.fcm_token
						server_key = str(settings.FIREBASE_SERVER_KEY)
						if seer_obj.device_type == 'Android':

							data_message = {		'type': 'appointment_status',
													'title' : 'APPOINTMENT STATUS',
													"message" : 'Your appointment '+appointment_obj.appointment_id+' has been accepted successfully.'
												}
							
							result = FCMNotification(api_key=server_key).notify_single_device(registration_id=registration_id,  data_message=data_message)
						if seer_obj.device_type == 'Ios':
							message_title = 'APPOINTMENT STATUS',
							message_body =  'Your appointment '+appointment_obj.appointment_id+' has been accepted successfully.'
							data_message = {		'type': 'appointment_status',
													'title' : 'APPOINTMENT STATUS',
													"message" : 'Your appointment '+appointment_obj.appointment_id+' has been accepted successfully.'
												}
							result = FCMNotification(api_key=server_key).notify_single_device(registration_id=registration_id, message_title=message_title, 
							message_body=message_body, data_message=data_message)

				else:
					cancellation_reason = request.data.get('cancellation_reason')
					if not cancellation_reason:
						return Response({'message': 'Cancellation reason is required'}, status=status.HTTP_404_NOT_FOUND)

					appointment_obj = FortuneAppointmentBook.objects.filter(id=appointment_id,fortune_teller=fortune_teller).first()
					if not appointment_obj:
						return Response({'message': 'Appointment not found'}, status=status.HTTP_404_NOT_FOUND)
					seer_obj =  SeerUser.objects.filter(id=appointment_obj.seer_user.id).first()
					# appoint_amount = appointment_obj.price
					# wallet_obj = FotuneTellerWallet.objects.filter(fortune_teller=fortune_teller).first()
					# if not wallet_obj:
					# 		wallet_obj = FotuneTellerWallet.objects.create(fortune_teller=fortune_teller,amount=0)
					# print("wallet amount",wallet_obj.amount)
					# print("appoint_amount",appoint_amount)

					# if wallet_obj.amount < appoint_amount:
					# 	return Response({'message': 'You cannot decline this appointment as you have insufficent refund amount on your wallet.'}, status=status.HTTP_404_NOT_FOUND)
					# remaining_amount = wallet_obj.amount - appoint_amount
					# wallet_obj.amount = remaining_amount
					# wallet_obj.save()
					
					# user_wallet = SeerUserWallet.objects.filter(seer_user =appointment_obj.seer_user ).first()
					# new_amount = user_wallet.amount + appoint_amount
					# user_wallet.amount = new_amount
					# user_wallet.save()
					# FortuneTellerTranscations.objects.create(transcation_id=generateTranscationsIdFortune(),seer_user=seer_obj,fortune_teller=fortune_teller,amount=appoint_amount,payment_mode='wallet',transcation_type="refund")
					# SeerUserTranscation.objects.create(transcation_id=generateTranscationsId(),transcation_type="refund",booking=appointment_obj,seer_user=seer_obj,amount=appoint_amount,payment_mode="wallet")
					appointment_obj.appointment_status = status_type
					appointment_obj.cancellation_reason = cancellation_reason
					appointment_obj.cancelled_by = 'Fortune'
					appointment_obj.save()
					transaction_obj = SeerUserTranscation.objects.filter(booking=appointment_obj).first()
					if not transaction_obj.charge_id:
						AdminRefundRequest.objects.create(appointment=appointment_obj,refund_amount=appointment_obj.price,cancellation_charges=0)
					SeerUserNotifications.objects.create(message='Your appointment '+appointment_obj.appointment_id+' has been declined.',notification_type="appointment_booking",seer_user= seer_obj)
					
					if seer_obj.notification_status:
						registration_id = seer_obj.fcm_token
						server_key = str(settings.FIREBASE_SERVER_KEY)
						if seer_obj.device_type == 'Android':

							data_message = {		'type': 'appointment_status',
													'title' : 'APPOINTMENT STATUS',
													"message" : 'Your appointment '+appointment_obj.appointment_id+' has been declined.'
												}
							
							result = FCMNotification(api_key=server_key).notify_single_device(registration_id=registration_id,  data_message=data_message)
						if seer_obj.device_type == 'Ios':
							message_title = 'APPOINTMENT STATUS',
							message_body =  'Your appointment '+appointment_obj.appointment_id+' has been declined.'
							data_message = {		'type': 'appointment_status',
													'title' : 'APPOINTMENT STATUS',
													"message" : 'Your appointment '+appointment_obj.appointment_id+' has been declined.'
												}
							result = FCMNotification(api_key=server_key).notify_single_device(registration_id=registration_id, message_title=message_title, 
							message_body=message_body, data_message=data_message)
					subject = 'Appointement Cancelled'
					html_message = render_to_string('appointment_cancelled.html', {'appoint_id': appointment_obj.appointment_id,'fortune_teller_name':appointment_obj.fortune_teller.first_name+' '+appointment_obj.fortune_teller.last_name,'service_name':appointment_obj.service.service_name,'price':appointment_obj.price,'cancel_reason':cancellation_reason})
					plain_message = html_message
					from_email = settings.EMAIL_HOST_USER
					to = appointment_obj.seer_user.email
					mail.send_mail(subject, plain_message, from_email, [to], html_message=html_message)
					appointment_obj = FortuneAppointmentBook.objects.filter(id=appointment_id,fortune_teller=fortune_teller).first()
					SeerUserNotifications.objects.create(message='Your appointment '+appointment_obj.appointment_id+' has been declined.',notification_type="appointment_booking",seer_user= seer_obj)

				return Response({'message':'Success'})
			else:
				return Response({'message':'Status type must be Accepted/Declined '})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		


class PastUpcomingAppointments(APIView):
	def get(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			appoint_type = request.query_params.get('appoint_type')
			if not appoint_type:
				return Response({'message':'appointment_type is required'},status=status.HTTP_400_BAD_REQUEST)
			if appoint_type == 'accepted':
				appoint_obj = FortuneAppointmentBook.objects.filter(fortune_teller=fortune_teller,appointment_status='Accepted').order_by('-id')
				serialize_data = AppointmentRequestListSerializer(appoint_obj,many=True).data
			else:
				appoint_obj = FortuneAppointmentBook.objects.filter(fortune_teller=fortune_teller).exclude(appointment_status__in=['Pending', 'Accepted']).order_by('-id')
				serialize_data = AppointmentRequestListSerializer(appoint_obj,many=True).data
			return Response({'message': 'Success', 'data': serialize_data})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		


class AddMoneyFortuneWallet(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			data = request.data
			payment_token = data.get('payment_token')
			if not payment_token:
				return Response({'message':'payment_token is required'},status=status.HTTP_400_BAD_REQUEST)
			amount = data.get('amount')
			if not amount:
				return Response({'message':'amount is required'},status=status.HTTP_400_BAD_REQUEST)
			stripe.api_key =settings.STRIPE_SECRET_KEY
			charge = stripe.Charge.create(
				amount=int(amount) * 100,
				currency='usd',
				source=payment_token,
				description='Adding money to wallet'
			)
			fortune_teller_wallet = fortune_teller.wallet.first()

			if fortune_teller_wallet:
				fortune_teller_wallet.amount += int(amount)
				fortune_teller_wallet.save()
			else:
				FotuneTellerWallet.objects.create(
					fortune_teller=fortune_teller,
					amount=amount
				)
			AdminNotifications.objects.create(message=fortune_teller.first_name+' '+fortune_teller.last_name+' fortune teller added money to their wallet.',type='fortuneteller_wallet')
			
			return Response({'message': 'Money added to wallet successfully'})

		except stripe.error.CardError as e:
			return Response({'message': str(e)}, status=status.HTTP_400_BAD_REQUEST)

		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)




class GetFortuneWalletDetails(APIView):
	def get(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			wallet_detail = FotuneTellerWallet.objects.filter(fortune_teller=fortune_teller).first()
			serializer = ForutuneTellerWalletSerializer(wallet_detail).data

			# wallet_transcation = FortuneTellerTranscations.objects.filter(fortune_teller = fortune_teller, payment_mode='wallet')[:3]
			# transcation_serializer = WalletTranscationSerializer(wallet_transcation,many=True).data

			return Response({'message': 'Success', 'data': serializer})

		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		


class GetFortuneWalletAllTranscation(APIView):
	def get(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			wallet_transcation = FortuneTellerTranscations.objects.filter(fortune_teller = fortune_teller, payment_mode='wallet')
			transcation_serializer = WalletTranscationSerializer(wallet_transcation,many=True).data
			return Response({'message': 'Success','data':transcation_serializer})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class MarkBookingCompleted(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			appointment_id = request.data.get('appointment_id')
			if not appointment_id:
				return Response({'message': 'appointment_id not found'}, status=status.HTTP_404_NOT_FOUND)
			appointment_obj = FortuneAppointmentBook.objects.filter(id=appointment_id).first()
			if not appointment_obj:
				return Response({'message': 'Appointment not found'}, status=status.HTTP_404_NOT_FOUND)
			general_obj =GeneralSettings.objects.all().first()
			if general_obj:
				commision_percent = general_obj.commission_percentage
				fortune_teller_wallet = appointment_obj.price * (commision_percent / 100)
				commision_amount = int(appointment_obj.price) - int(fortune_teller_wallet)
			else:
				commision_amount= int(0)
			fortune_obj = FortuneTeller.objects.filter(id=appointment_obj.fortune_teller_id,end_date__isnull=True).first()
			wallet_obj = FotuneTellerWallet.objects.filter(fortune_teller=appointment_obj.fortune_teller_id).first()
			if wallet_obj:
				wallet_obj.amount += commision_amount
				wallet_obj.save()
			else:
				FotuneTellerWallet.objects.create(fortune_teller=fortune_obj,amount=commision_amount)

			seer_user_obj = SeerUser.objects.filter(id=appointment_obj.seer_user_id).first()
			FortuneTellerTranscations.objects.create(transcation_id=generateTranscationsIdFortune(),seer_user=seer_user_obj,fortune_teller=fortune_obj,amount=commision_amount,payment_mode='wallet',transcation_type="appointment")
			appointment_obj.appointment_completed = True
			appointment_obj.save()
			SeerUserNotifications.objects.create(message='You appointment :'+appointment_obj.appointment_id+ ' has been completed successfully.',notification_type="appointment_completed",seer_user=seer_user_obj)
			FortuneTellerNotifications.objects.create(message='Amount of $'+str(commision_amount)+ ' for the appointment '+appointment_obj.appointment_id+' has been added to your wallet successfully.',notification_type="appointment_earning",fortune_teller=fortune_obj)
			return Response({'message': 'Success'})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class PayoutMoney(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			payout_amount =  request.data.get('payout_amount')
			if not payout_amount:
				return Response({'message': 'Payout amount is required'}, status=status.HTTP_404_NOT_FOUND)
			wallet_obj = FotuneTellerWallet.objects.filter(fortune_teller = fortune_teller.id).first()
			if int(wallet_obj.amount) < int(payout_amount):
				return Response({'message': 'You do not have sufficent amount in you wallet.'}, status=status.HTTP_404_NOT_FOUND)
			wallet_obj.amount -= int(payout_amount)
			wallet_obj.save()
			FortunePayoutTranscation.objects.create(transcation_id = generatePayoutTranscationsId(),fortune_teller=fortune_teller,amount= payout_amount)
			AdminNotifications.objects.create(message=fortune_teller.first_name+' '+fortune_teller.last_name+' fortune teller has send a request for the payout of $' +payout_amount,type='fortuneteller_payout')
			return Response({'message': 'Success'})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class AllPayoutTranscations(APIView):
	def get(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			payout_obj = FortunePayoutTranscation.objects.filter(fortune_teller=fortune_teller).order_by('-id')
			transcation_type = request.query_params.get('transcation_type')
			if not transcation_type:
				return Response({'message':'transcation_type is required'},status=status.HTTP_400_BAD_REQUEST)
			
			if transcation_type == "pending":
				payout_obj = FortunePayoutTranscation.objects.filter(fortune_teller=fortune_teller,transcation_status='pending')
				transcation_serializer = PayoutTranscationSerializer(payout_obj,many=True).data
			elif transcation_type == 'approved':
				payout_obj = FortunePayoutTranscation.objects.filter(fortune_teller=fortune_teller,transcation_status='approved')
				transcation_serializer = PayoutTranscationSerializer(payout_obj,many=True).data
			else:
				payout_obj = FortunePayoutTranscation.objects.filter(fortune_teller=fortune_teller).order_by('-id')
				transcation_serializer = PayoutTranscationSerializer(payout_obj,many=True).data

			return Response({'message': 'Success','data':transcation_serializer})

		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class dummyNotification(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			seer_user = SeerUser.objects.filter(id=62).first()

			if seer_user.notification_status:
				registration_id = seer_user.fcm_token
				server_key = str(settings.FIREBASE_SERVER_KEY)
				if seer_user.device_type == 'Android':

					data_message = {		'type': 'conversation_start',
											'title' : 'CHAT STARTED FROM FORTUNE SIDE',
											'message' : 'Your Chat have started with'+ fortune_teller.first_name+' '+fortune_teller.last_name+', Please Join!',
											'image': fortune_teller.image,
											'twilio_channel_sid':'CHf934bfe890d049339346dd180726c48b',	
										}
					
					result = FCMNotification(api_key=server_key).notify_single_device(registration_id=registration_id,  data_message=data_message)
				if seer_user.device_type == 'Ios':
					message_title = 'REQUEST ACCEPTED',
					message_body =  fortune_teller.first_name+' '+fortune_teller.last_name+' sent you a friend request.'
					data_message = {		'type': 'friend_request_accepted',
											'title' : 'REQUEST ACCEPTED',
											"message" :  fortune_teller.first_name+' '+fortune_teller.last_name+' accepted your friend request.'
										}
					result = FCMNotification(api_key=server_key).notify_single_device(registration_id=registration_id, message_title=message_title, 
					message_body=message_body, data_message=data_message)
			return Response({'message': 'Success'})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		
class OnlineStatus(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'user not found'}, status=status.HTTP_404_NOT_FOUND)
			data = request.data
			online_status = data.get('online_status')
			if not online_status:
				return Response({'message':'online_status is required'},status=status.HTTP_400_BAD_REQUEST)
			fortune_teller.is_online = online_status
			fortune_teller.save()
			return Response({'message':'Success'})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


"""=============================== CronJob functions ===================================="""
class ExpireAppointments(APIView):
	def get(self, request):
		try:
			# try:
			#     uid = authenticated(request)
			# except Exception as e:
			#     return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)


			# Query appointments that are not expired
			appointments_to_expire = FortuneAppointmentBook.objects.filter(
				appointment_status__in=['Pending', 'Accepted'],
			)
			# Update appointment statuses to 'Expired'
			for appointment in appointments_to_expire:

				appointment_time = appointment.appointment_time
				appointment_date = appointment.appointment_date
				booked_start, booked_end = map(str.strip, appointment_time.split('-'))
				appointment_datetime_start = datetime.strptime(appointment_date + ' ' + booked_start, "%d %B %Y %I:%M %p")
				appointment_datetime_end = datetime.strptime(appointment_date + ' ' + booked_end, "%d %B %Y %I:%M %p")

				appointment_timezone = pytz.timezone(appointment.timezone)

				start_time_appointment_timezone = appointment_timezone.localize(appointment_datetime_start)
				end_time_appointment_timezone = appointment_timezone.localize(appointment_datetime_end)
				# Convert the start and end times to the fortune teller's timezone
				start_time_appointment = start_time_appointment_timezone.astimezone(appointment_timezone)
				end_time_appointment = end_time_appointment_timezone.astimezone(appointment_timezone)

				# current_time = datetime.now()
				current_time = datetime.now(pytz.timezone (appointment.timezone))
				if current_time >= end_time_appointment:

					if appointment.appointment_status == 'Accepted':
						if appointment.twilio_channel_sid or appointment.twilio_room_name:
							appointment.appointment_status = 'Completed'
							appointment.appointment_completed = True
							appointment.save()
							general_obj =GeneralSettings.objects.all().first()
							if general_obj:
								commision_percent = general_obj.commission_percentage
								total_amount = appointment.price * (commision_percent / 100)
								commision_amount = int(appointment.price) - int(total_amount)
							else:
								commision_amount= appointment.price
								total_amount = 0
							"""========== This code transfer the amount to fortune teller connected stripe account ========="""
							fortune_obj = FortuneTeller.objects.filter(id=appointment.fortune_teller.id).first()
							if fortune_obj.is_stripe_account_connect:
								tranfer_amount = TransferToConnectedAccount(fortune_obj.stripe_connect_account_id,commision_amount,appointment.appointment_id)
								"""========== End Of Code ========="""
								
								"""========== This code transfer the amount to fortune teller wallet/Earning  ========="""
								wallet_obj = FotuneTellerWallet.objects.filter(fortune_teller=appointment.fortune_teller).first()
								if wallet_obj:
									wallet_obj.amount += commision_amount
									wallet_obj.save()
								else:    
									FotuneTellerWallet.objects.create(fortune_teller=appointment.fortune_teller,amount=commision_amount)
								"""========== End Of Code ========="""
						else:
							AdminRefundRequest.objects.create(appointment=appointment,refund_amount=appointment.price,cancellation_charges=0)
							appointment.appointment_status = 'Expired'
							appointment.cancellation_reason = 'Expired'
							appointment.cancelled_by = 'Expired'
							appointment.save()
				# else:
				# 	pass
				
					""" ======= This code initiate when appoitment is not accepted by fortune teller ========= """

					if appointment.appointment_status == 'Pending':
						transaction_obj = SeerUserTranscation.objects.filter(booking=appointment).first()
						if not transaction_obj.charge_id:
							AdminRefundRequest.objects.create(appointment=appointment,refund_amount=appointment.price,cancellation_charges=0)
						appointment.appointment_status = 'Expired'
						appointment.cancellation_reason = 'Expired'
						appointment.cancelled_by = 'Expired'
						appointment.save()

					""" ======= End of Code ========= """

			return Response({'message': 'Expired appointments updated successfully'}, status=status.HTTP_200_OK)

		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)




class UpdateOnlineStatus(APIView):
	def get(self,request):
		try:
			# Find fortune tellers who haven't used the application recently
			inactive_fortune_tellers = FortuneTeller.objects.filter(
				is_online=True,
				last_activity__lt=datetime.now() - timedelta(hours=12)
			)
			# Update their online status to False
			for fortune_teller in inactive_fortune_tellers:
				fortune_teller.is_online = False
				fortune_teller.save()
			return Response ({'message':'Success'})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


"""=============================== End CronJob functions ===================================="""

# class ExpireAppointments(APIView):
# 	def get(self, request):
# 		try:
# 			# try:
# 			# 	uid = authenticated(request)
# 			# except Exception as e:
# 			# 	return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)

# 			# Get the current date and time
# 			current_datetime = datetime.now()

# 			# Query appointments that are not expired
# 			appointments_to_expire = FortuneAppointmentBook.objects.filter(
# 				appointment_status__in=['Pending', 'Accepted'],
# 				appointment_date__lt=current_datetime
# 			)

# 			# Update appointment statuses to 'Expired'
# 			for appointment in appointments_to_expire:
# 				if appointment.appointment_status == 'Accepted':
# 					if appointment.twilio_channel_sid or appointment.twilio_room_name:
# 						appointment.appointment_status = 'Expired'
# 						appointment.save()
# 						general_obj =GeneralSettings.objects.all().first()
# 						if general_obj:
# 							commision_percent = general_obj.commission_percentage
# 							total_amount = appointment.price * (commision_percent / 100)
# 							commision_amount = int(appointment.price) - int(total_amount)
# 						else:
# 							commision_amount= appointment.price
# 							total_amount = 0
# 						"""========== This code transfer the amount to fortune teller connected stripe account ========="""
# 						fortune_obj = FortuneTeller.objects.filter(id=appointment.fortune_teller.id).first()
# 						if fortune_obj.is_stripe_account_connect:
# 							tranfer_amount = TransferToConnectedAccount(fortune_obj.stripe_connect_account_id,commision_amount)
# 							"""========== End Of Code ========="""
							
# 							"""========== This code transfer the amount to fortune teller wallet/Earning  ========="""
# 							wallet_obj = FotuneTellerWallet.objects.filter(fortune_teller=appointment.fortune_teller).first()
# 							if wallet_obj:
# 								wallet_obj.amount += commision_amount
# 								wallet_obj.save()
# 							else:	
# 								FotuneTellerWallet.objects.create(fortune_teller=appointment.fortune_teller,amount=commision_amount)
# 							"""========== End Of Code ========="""
# 					else:
# 						appointment.appointment_status = 'Expired'
# 						appointment.save()

# 				""" ======= This code initiate when appoitment is not accepted by fortune teller ========= """

# 				if appointment.appointment_status == 'Pending':
# 					appointment.appointment_status = 'Expired'
# 					appointment.save()

# 				""" ======= End of Code ========= """

# 			return Response({'message': 'Expired appointments updated successfully'}, status=status.HTTP_200_OK)

# 		except Exception as e:
# 			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		


# class SuccessPageUrl(TemplateView):
# 	template_name = 'success.html'

class SuccessPageUrl(APIView):
	def get(self,request):
		try:
			fortune_id = request.GET.get('fortune')
			fortune_Obj = FortuneTeller.objects.filter(id = fortune_id).first()
			account_id = fortune_Obj.stripe_connect_account_id
			# Retrieve the account details
			account = stripe.Account.retrieve(account_id)
			print('account===========',account)
			fortune_Obj.is_stripe_account_connect = True
			if account['charges_enabled']:
				fortune_Obj.is_stripe_verified = True
				fortune_Obj.save()
				return render(request,'success.html')
			else:
				fortune_Obj.save()
				return render(request,'link-expire.html')
		except  Exception as e:
			return render(request,'link-expire.html')



class StripeConnectAccount(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
		
			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'user not found'}, status=status.HTTP_404_NOT_FOUND)
			data = request.data
			fortune_email = fortune_teller.email
			if fortune_teller.stripe_connect_account_id:
				print('iff',fortune_teller.stripe_connect_account_id)
				stripe_connect_url = create_account_url(fortune_teller.stripe_connect_account_id,fortune_teller.id)
			else:
				connect_account_id =create_stripe_connectAccount(fortune_email)
				if connect_account_id:
					fortune_teller.stripe_connect_account_id = connect_account_id
					stripe_connect_url = create_account_url(connect_account_id,fortune_teller.id)
					fortune_teller.save()

			return Response({'message': 'Success','data':stripe_connect_url}, status=status.HTTP_200_OK)

		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class DeleteFortuneAccountView(generics.DestroyAPIView):
	def destroy(self, request):
		try:
			uid = authenticated(request)
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)
	
		fortune_teller = FortuneTeller.objects.filter(id=uid).first()
		if not fortune_teller:
			return Response({'message': 'user not found'}, status=status.HTTP_404_NOT_FOUND)
		fortune_id = uid

		# Check if user_id is provided in the request data
		if fortune_id is None:
			return Response({'message': 'fortune_id is required'}, status=status.HTTP_404_NOT_FOUND)
		try:
			user = FortuneTeller.objects.get(id=fortune_id)
		except user.DoesNotExist:
			return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
		user.account_deleted = True
		user.save()
		return Response({"message": "Fortune teller deleted successfully"}, status=200)