from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from user_panel.models import *
import random
from datetime import datetime,date
from django.conf import settings
from passlib.hash import django_pbkdf2_sha256 as handler
import json
from admin_panel.models import *
from rest_framework.authentication import get_authorization_header
import jwt
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework_simplejwt.backends import TokenBackend
from django.core.mail import EmailMultiAlternatives
from rest_framework import exceptions
from django.shortcuts import render, redirect,HttpResponse
from django.core import mail
from django.template.loader import render_to_string
import math, random, pytz, string
from django.contrib import messages
from admin_panel.functions import *
from django.utils.timesince import timesince
from django.db.models import Max
from django.db.models import Q
import ast
from .functions import *
from pyfcm import FCMNotification
import csv
from twilio.jwt.access_token.grants import (
	SyncGrant,
	ChatGrant,
	VideoGrant
)
from twilio.rest import Client
from twilio.jwt.access_token import AccessToken
# from serpapi import GoogleSearch
from . import forms
# Create your views here.


account_sid= settings.TWILIO_ACCOUNT_SID
auth_token = settings.TWILIO_AUTH_TOKEN
chat_service_sid = settings.TWILIO_CHAT_SID
sync_service_sid = settings.TWILIO_SYNC_SID
api_sid = settings.TWILIO_API_SID
api_secret= settings.TWILIO_API_SECRET
client = Client(account_sid, auth_token)


def gernateBookingId():
	lastObj= UserBookings.objects.all().last()
	if lastObj:
		if not lastObj.booking_id:
			return 'BOOK0001'

		theId=lastObj.booking_id
		theId=theId[4:]
		theId=int(theId)+1
		theId=str(theId)
		theId=theId.zfill(4)
		return "BOOK"+str(theId)
	else:
		return 'BOOK0001'


def generateTranscationsId():
	lastObj= UserTranscation.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'

class getPrivacyPolicy(APIView):
	def get(self,request):
		try:
			page_type_param =  self.request.query_params.get('page_type_param')
			if page_type_param == 'Privacy':
				data_obj = ContentPages.objects.filter(page_type='Privacy').first()
			else:
				data_obj = ContentPages.objects.filter(page_type='Terms').first()
			if not data_obj:
				all_data={}
			else:
				all_data = {
					'id':data_obj.id,
					'title':data_obj.title,
					'content':data_obj.content
				}
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Success','data':all_data})
		except Exception as e:
			print(e)
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class getTermsConditions(APIView):
	def get(self,request):
		try:
			terms_obj = ContentPages.objects.filter(page_type='Terms').first()
			if not terms_obj:
				all_data={}
			else:
				all_data = {
					'id':terms_obj.id,
					'title':terms_obj.title,
					'content':terms_obj.content
				}
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Success','data':all_data})
		except Exception as e:
			print(e)
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class faqListing(APIView):
	def get(self,request):
		try:
			faq_obj = Faq.objects.filter(end_date__isnull =True).order_by('-id')
			all_Data =[]
			for faq in faq_obj:
				all_data = {
					'id':faq.id,
					'title':faq.title,
					'content':faq.content
				}
				all_Data.append(all_data)
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Success','data':all_Data})
		except Exception as e:
			print(e)
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)




class userRegister(APIView):
	def post(self,request):
		try:
			first_name = request.data.get('first_name')
			if not first_name:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'first_name is required'},status=status.HTTP_400_BAD_REQUEST)
			last_name = request.data.get('last_name')
			if not last_name:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'last_name is required'},status=status.HTTP_400_BAD_REQUEST)
			email = request.data.get('email').lower()
			if not email:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Email is required'},status=status.HTTP_400_BAD_REQUEST)
			check_email = User.objects.filter(email=email).first()
			if check_email:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'This email is already registered with us.'},status=status.HTTP_400_BAD_REQUEST)
			password = request.data.get('password')
			if not password:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Password is required'},status=status.HTTP_400_BAD_REQUEST)
			confirm_password = request.data.get('confirm_password')
			if not confirm_password:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Confirm Password is required'},status=status.HTTP_400_BAD_REQUEST)
			if password != confirm_password:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Password and Confirm Password are not same.'},status=status.HTTP_400_BAD_REQUEST)

			string_password =  confirm_password
			final_password = handler.hash(string_password)
			check_customerObj = User.objects.filter(email = email,is_email_verified = False).first()
		   
			customerObj=User.objects.create(password = final_password,email=email,first_name=first_name,last_name=last_name,is_user = True)
			ran_num = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(12)])
			baselink =  '/api-user/email-verification/' + str(customerObj.email) + '/' + ran_num
			completelink = str(settings.BASE_URL) + baselink
			customerObj.email_verify_link = baselink
			customerObj.save()
			subject = 'Email Verification'
			html_message = render_to_string('worker_email_verification.html', {'link': completelink})
			plain_message = html_message
			from_email = 'support@olfix.co.uk'
			to = email
			mail.send_mail(subject, plain_message, from_email, [to], html_message=html_message)
			subject = 'New User Registered'
			from datetime import date
			today = date.today()

			html_message = render_to_string('new_user_registered.html', {'first_name': first_name,'last_name':last_name,'email':email,'date':today})
			plain_message = html_message
			from_email = 'support@olfix.co.uk'
			to = 'superadmin@yopmail.com'
			mail.send_mail(subject, plain_message, from_email, [to], html_message=html_message)
			
			return Response({'status_code':status.HTTP_200_OK,'status_message':'You have been successfully registered with us.Please verify your email.'})
		except Exception as e:
			print(e)
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)




class userEmailVerification(APIView):
	def get(self,request):
		try:
			link = str(self.request.path)
			print(link)
			user_email = link.split('/')[-2]
			
			user_obj = User.objects.filter(email = user_email, email_verify_link = link).first()
			user_obj.is_email_verified = True
			user_obj.user_stripe_id = generate_strip_id()
			UserWallet.objects.create(user=user_obj,amount=0)
			user_obj.save()
			AdminNotifications.objects.create(message = "A new user "+user_obj.first_name+" "+user_obj.last_name+" has been registered successfully",type="new_user")
			return render(request,'email_verified_success.html')	
		except Exception as e:
			print(e)
			return render(request,'email_verified_success.html')	



class userLogin(APIView):
	def post(self,request):
		try:
			email = request.data.get('email')
			if not email:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Email is required'},status=status.HTTP_400_BAD_REQUEST) 
			password = request.data.get('password')
			if not password:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Password is required'},status=status.HTTP_400_BAD_REQUEST)  
			user  = User.objects.filter(email=email,is_user = 1).count()
			user_status  = User.objects.filter(email=email,is_user = 1).first()

			if user == 0:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'This email does not exist in our database, please register'},status=status.HTTP_400_BAD_REQUEST)
			if user_status.status == 0:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Account not yet activated. Please contact support'},status=status.HTTP_400_BAD_REQUEST)

			if user_status.end_date is not None:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'This account is deleted.'},status=status.HTTP_400_BAD_REQUEST)

			check_verification =  User.objects.filter(email=email,is_email_verified = False,is_user = 1).first()
			if check_verification:
				ran_num = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(12)])
				baselink =  '/api-user/email-verification/' + str(check_verification.email) + '/' + ran_num
				completelink = str(settings.BASE_URL) + baselink
				check_verification.email_verify_link = baselink
				check_verification.save()
				subject = 'Email Verification'
				html_message = render_to_string('user_email_verification.html', {'link': completelink})
				plain_message = html_message
				from_email = 'support@olfix.co.uk'
				to = email
				mail.send_mail(subject, plain_message, from_email, [to], html_message=html_message) 
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Please check your email for verification'},status=status.HTTP_400_BAD_REQUEST)

			userObj  = User.objects.filter(email=email,is_email_verified=True,is_user = 1).first()
			if not userObj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'No account found'},status=status.HTTP_400_BAD_REQUEST)
			device_token = request.data.get('device_token')
			if not device_token:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Device token is required'},status=status.HTTP_400_BAD_REQUEST)
			userObj.device_token = device_token
			userObj.save()
			new_pass = userObj.password
			check = handler.verify(request.data.get('password'),new_pass)
			if check:
				refresh_token = RefreshToken.for_user(userObj)
				allData={'user_id':userObj.id,
					'email':userObj.email,
					'first_name':userObj.first_name,
					'last_name':userObj.last_name,
					'device_token':userObj.device_token,
					'refresh': str(refresh_token),
					'access': str(refresh_token.access_token),
				   }
				return Response({'status_code':status.HTTP_200_OK,'status_message':'Login Successfully','data':allData})
			else:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Invalid password'},status=status.HTTP_400_BAD_REQUEST)
		except Exception as e:
			print(e)
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class userForgetPassword(APIView):
	def post(self,request):
			email = request.data.get('email')
			if not email:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Email is required'},status=status.HTTP_400_BAD_REQUEST)
			
			user  = User.objects.filter(email= email).first()
			if not user:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'This email does not exist in our database, please enter the valid email address.'},status=status.HTTP_400_BAD_REQUEST)
			userObj  = User.objects.filter(email=email).first()
			if userObj:
				ran_num = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(12)])
				baselink =  '/api-user/forgoten/' + str(userObj.email) + '/' + ran_num
				completelink = str(settings.BASE_URL) + baselink
				userObj.forgot_password_link = baselink
				userObj.save()
				subject = 'Forgot Password'
				html_message = render_to_string('user_forget_password_email.html', {'link': completelink})
				plain_message = html_message
				from_email = 'support@olfix.co.uk'
				to = email
				mail.send_mail(subject, plain_message, from_email, [to], html_message=html_message)
				return Response({'status_code':status.HTTP_200_OK,'status_message':'Reset password link has been sent to this email address.'})
			else:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Email not exists'},status=status.HTTP_400_BAD_REQUEST)


class forgetPasswordVerification(APIView):
	def get(self,request):
		link = str(self.request.path)
		print(link)
		user_email = link.split('/')[-2]
		link_expiry = User.objects.filter(email = user_email).first()
		if link_expiry.forgot_password_link == "LinkExpiry":
			return render(request,'link-expire.html')
		user_obj = User.objects.filter(email = user_email, forgot_password_link = link).first()
		
		if user_obj:
			print('True')
			valid = True
		else:
			print('False')
			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]
			print(user_email)
			user_obj = User.objects.filter(email = user_email).first()
			if user_obj:
				user_obj.set_password(new_password)
				user_obj.forgot_password_link = "LinkExpiry"
				user_obj.save()
				messages.success(request, "Changed successfully")
				return render(request,'password_success.html')
		else:
			return render(request, 'forgot.html', {'form': form})

class userUpdateProfile(APIView):
	def get(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('User is inactive.')
			all_data = {
				'user_id':user_obj.id,
				'avatar':user_obj.avatar,
				'email':user_obj.email,
				'first_name':user_obj.first_name,
				'last_name':user_obj.last_name,
				'phone_number':user_obj.phone_number,
				'adress':user_obj.address,
				'latitude':user_obj.latitude,
				'longitude':user_obj.longitude,
				'dob':user_obj.dob,
				'gender':user_obj.gender,





			}
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Success','data':all_data})
		except Exception as e:
			print(e)
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)

	def post(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
			first_name = request.data.get('first_name')
			if not first_name:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'First name is required'},status=status.HTTP_400_BAD_REQUEST)
			last_name = request.data.get('last_name')
			if not last_name:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Last name is required'},status=status.HTTP_400_BAD_REQUEST)
			phone_number = request.data.get('phone_number')
			if not phone_number:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Phone number is required'},status=status.HTTP_400_BAD_REQUEST)
			phone_check = User.objects.filter(phone_number = phone_number).exclude(id=user_obj.id)
			if phone_check:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'This phone is already associated with some account.'},status=status.HTTP_400_BAD_REQUEST)
			address = request.data.get('address')
			if not address:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'address is required'},status=status.HTTP_400_BAD_REQUEST)

			latitude = request.data.get('latitude')
			if not latitude:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'latitude is required'},status=status.HTTP_400_BAD_REQUEST)

			longitude = request.data.get('longitude')
			if not longitude:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'longitude is required'},status=status.HTTP_400_BAD_REQUEST)

			avatar = request.data.get('avatar')
			if not avatar:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'avatar is required'},status=status.HTTP_400_BAD_REQUEST)

			email = request.data.get('email')
			if not email:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Email is required'},status=status.HTTP_400_BAD_REQUEST)
			email_check = User.objects.filter(email = email).exclude(id=user_obj.id)
			if email_check:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'This email is already associated with some account.'},status=status.HTTP_400_BAD_REQUEST)
			
			dob = request.data.get('dob')

			gender = request.data.get('gender')

			user_obj.first_name = first_name
			user_obj.last_name = last_name
			user_obj.phone_number = phone_number
			user_obj.email = email
			user_obj.address = address
			user_obj.latitude = latitude
			user_obj.longitude = longitude
			user_obj.dob = dob
			user_obj.gender = gender
			user_obj.avatar = '/'+avatar
			user_obj.save()
			all_data = {
				'user_id':user_obj.id,
				'avatar':user_obj.avatar,
				'email':user_obj.email,
				'first_name':user_obj.first_name,
				'last_name':user_obj.last_name,
				'phone_number':user_obj.phone_number,
				'address':user_obj.address,
				'latitude':user_obj.latitude,
				'longitude':user_obj.longitude,
				'dob':user_obj.dob,
				'gender':user_obj.gender,
			}
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Profile updated successfully','data':all_data})
		except Exception as e:
			print(e)
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class phoneOtpVerification(APIView):
	def post(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
			otp =  request.data.get('otp')
			if not otp:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'OTP is required'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.otp == otp:
				user_obj.is_otp_verified = True
				user_obj.save()
				return Response({'status_code':status.HTTP_200_OK,'status_message':'OTP verified successfully.'},status=status.HTTP_200_OK) 
			else:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'OTP is not correct'},status=status.HTTP_400_BAD_REQUEST) 

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


class userChangePassword(APIView):
	def post(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
			old_password = request.data.get('old_password')
			if not old_password:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'old password is required.'},status=status.HTTP_400_BAD_REQUEST)
			new_password = request.data.get('new_password')
			if not new_password:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'new password is required.'},status=status.HTTP_400_BAD_REQUEST)
			new_confirm_password = request.data.get('new_confirm_password')
			if not new_confirm_password:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'new confirm password is required.'},status=status.HTTP_400_BAD_REQUEST)
			
			if user_obj.check_password(old_password) == False:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Does not match with the old password.'},status=status.HTTP_400_BAD_REQUEST)
			if new_confirm_password == user_obj.check_password(old_password):
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Cannot set old password as new password.'},status=status.HTTP_400_BAD_REQUEST)

			password = new_confirm_password
			user_obj.set_password(password)
			user_obj.save()
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Password Changed Successfully.'}) 
		except Exception as e:
			print(e)
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class userDeleteAccount(APIView):
	def post(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
			user_obj.end_date = datetime.datetime.now()
			user_obj.save()
			chat_obj = Conversation.objects.filter(user =user_obj.id )
			for chat in chat_obj:
				chat.end_date = datetime.datetime.now()
				chat.save()
			rating_obj = ServiceProviderRatingReviews.objects.filter(user =user_obj.id)
			for rate in rating_obj:
				rate.end_date = datetime.datetime.now()
				rate.save()
			trans_obj = UserTranscation.objects.filter(user=user_obj.id)
			for trans in trans_obj:
				trans.end_date = datetime.datetime.now()
				trans.save()
			book_obj = UserBookings.objects.filter(user = user_obj.id)
			for book in book_obj:
				book.end_date = datetime.datetime.now()
				book.save()
			cards_obj = UserCards.objects.filter(user = user_obj.id)
			for card in cards_obj:
				card.end_date = datetime.datetime.now()
				card.save()
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Account deleted successfully'}) 
			
		except Exception as e:
			print(e)
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class getCustomerNotifications(APIView):
	def get(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
			notify_obj = CustomerNotifications.objects.filter(customer=user_obj.id,end_date__isnull = True).order_by('-id')
			allData=[]
			for notify in notify_obj:
				alldata = {
					'id':notify.id,
					'message': notify.message,
					'notification_type' : notify.type,
					'start_date':timesince(notify.start_date)+' ago',
				}
				allData.append(alldata)
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','data':allData})
		except Exception as e:
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class deleteCustomerNotifications(APIView):
	def post(self,request):
		token = get_authorization_header(request)
		if token is None or token == "null" or token.strip() == "":
			raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
		decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
		user_id = decoded['user_id']
		user_obj =  User.objects.filter(id = user_id,is_user=1).first()
		if not user_obj:
			return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
		if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
		notification_id =  request.data.get('notification_id')
		if not notification_id:
			return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Notification Id is required'},status=status.HTTP_400_BAD_REQUEST)
		CustomerNotifications.objects.filter(id=notification_id).update(end_date=datetime.now())
		return Response({'status_code':status.HTTP_200_OK,'status_message':'Notification Deleted Successfully'})

class HelpSupportUser(APIView):
	def post(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
			title = request.data.get('title')
			if not title:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'title is required'},status=status.HTTP_400_BAD_REQUEST)
			description = request.data.get('description')
			if not description:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'description is required'},status=status.HTTP_400_BAD_REQUEST)
			HelpSupport.objects.create(title=title,description=description,user_id=user_obj.id)
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Help & Support Send Successfully'})
		except Exception as e:
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)




class getCategoryList(APIView):
	def get(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
			category_obj = Category.objects.filter(end_date__isnull=True)
			all_Data = []
			for cat in category_obj:
				all_data = {
					'id':cat.id,
					'image':cat.image,
					'name':cat.name,
				}
				all_Data.append(all_data)
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','data':all_Data})
		except Exception as e:
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class getSubCategoryList(APIView):
	def get(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
			main_id = request.query_params.get('main_id')
			if not main_id:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Main id is required'},status=status.HTTP_400_BAD_REQUEST)
			sub_obj = SubCategory.objects.filter(category_id = main_id, end_date__isnull = True)
			if not sub_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'No subcategory found'},status=status.HTTP_400_BAD_REQUEST)

			sub_Data =[]
			for sub in sub_obj:
				sub_data = {
					'id':sub.id,
					'main_id':sub.category_id,
					'main_category_name':sub.category.name,
					'sub_category_name':sub.name,
					'image':sub.image,
				}
				sub_Data.append(sub_data)

			params = {
			"engine": "google_news",
			"q": sub.category.name,
			"api_key": "699adbd41323e344848401bfb91509dade9c5831b9a3e63414b8096331a2436f",
			}

			# search = GoogleSearch(params)
			# results = search.get_dict()
			# news_results = results["news_results"]
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','data':sub_Data}) 
		except Exception as e:
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class getServiceProviders(APIView):
	def get(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
			sub_service_id = request.query_params.get('sub_service_id')
			if not sub_service_id:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Sub service id is required'},status=status.HTTP_400_BAD_REQUEST)
			worker_obj = WorkerServices.objects.filter(sub_services_id = sub_service_id,worker__is_worker_approved =1)
			all_Data = []
			other_settings = OtherSettings.objects.all().first()
			for worker in worker_obj:
				all_data = {
					'worker_id':worker.worker_id,
					'worker_name':worker.worker.first_name+" "+worker.worker.last_name,
					'worker_image':worker.worker.avatar,
					'worker_experience':worker.worker.experience,
					'price':worker.price,
					'ratings':worker.worker.ratings,
					'time_taken':worker.time_taken,
					'platform_fee': other_settings.platform_fee,
					'admin_commission': other_settings.admin_commission,

				}
				all_Data.append(all_data)
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','data':all_Data}) 
		except Exception as e:
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)

class getServiceProvidersDetails(APIView):
	def get(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
			service_provider_id = request.query_params.get('service_provider_id')
			if not service_provider_id:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Service provider id is required'},status=status.HTTP_400_BAD_REQUEST)
			worker_obj =  User.objects.filter(id = service_provider_id ,is_worker = 1).first()
			worker_data = {
				'worker_id': worker_obj.id,
				'worker_name':worker_obj.first_name+" "+worker_obj.last_name,
				'worker_image':worker_obj.avatar,
				'worker_experience':worker_obj.experience,
				'worker_email':worker_obj.email,
				'worker_address':worker_obj.address,
			}
			previous_works = WorkerWorkImages.objects.filter(worker_id=worker_obj.id)
			all_Work = []
			for work in previous_works:
				all_work = {
					'id':work.id,
					'image':work.image,
				} 
				all_Work.append(all_work)
			review_obj = ServiceProviderRatingReviews.objects.filter(service_provider = service_provider_id )
			review_Data = []
			for review in review_obj:
				all_review = {
					'id':review.id,
					'rating':review.rating,
					'review':review.review,
					'customer_name':review.user.first_name+' '+review.user.last_name,
					'customer_avatar':review.user.avatar,
					'booking_id':review.booking.booking_id,
					'created_at':review.start_date,
				}
				review_Data.append(all_review)
			other_settings = OtherSettings.objects.all().first()
			other_setting_data = {
				'id': other_settings.id,
				'platform_fee': other_settings.platform_fee,
				'admin_commission': other_settings.admin_commission,
			}
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','worker_data':worker_data,'past_work':all_Work,'review_data':review_Data,'total_ratings':worker_obj.ratings,'other_setting_data':other_setting_data}) 
		except Exception as e:
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class getServiceProviderTimeslots(APIView):
	def get(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
			worker_id = request.query_params.get('worker_id')
			if not worker_id:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Worker id is required'},status=status.HTTP_400_BAD_REQUEST)

			check_slots =  WorkerTimeSlots.objects.filter(worker_id = worker_id).first()
			if check_slots:
				data_json = json.loads( check_slots.slots.replace("\\", ""))

				all_data =  data_json
			else:
				all_data = {} 
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','data':all_data}) 
					
		except Exception as e:
			return Response({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class addUserCard(APIView):
	def post(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			card_id = request.data.get('card_id')
			if not card_id:
				return Response({'message': 'card_id is required'}, status=status.HTTP_400_BAD_REQUEST)
			if not user_obj.user_stripe_id:
				user_obj.user_stripe_id = generate_strip_id()
				user_obj.save()
			if user_obj.user_stripe_id:
				user_id = user_obj.user_stripe_id
				stripe.api_key = settings.STRIPE_SECRET_KEY
				createCard = stripe.Customer.create_source(user_id,source=card_id)
				if createCard:
					cardObj = UserCards.objects.create(user=user_obj,card_id=createCard['id'],exp_month=createCard['exp_month'],exp_year=createCard['exp_year'],the_user_stripe=createCard['customer'],last_digits=createCard['last4'])
					alldata = {
						'id':cardObj.id,
						'user_id':cardObj.user_id,
						'card_id':cardObj.card_id,
						'exp_month':cardObj.exp_month,
						'exp_year':cardObj.exp_year,
						'the_user_stripe':cardObj.the_user_stripe,
						'last_digits':cardObj.last_digits,
						'is_default':cardObj.is_default,
					} 
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','data':alldata}) 
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class getUserCard(APIView):
	def get(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			card_obj = UserCards.objects.filter(user = user_obj)
			all_Data = []
			for card in card_obj:
				all_data = {
					'id':card.id,
					'user_id':card.user_id,
					'card_id':card.card_id,
					'exp_month':card.exp_month,
					'exp_year':card.exp_year,
					'the_user_stripe':card.the_user_stripe,
					'last_digits':card.last_digits,
					'is_default':card.is_default,
				}
				all_Data.append(all_data)
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','data':all_Data}) 
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class deleteUserCard(APIView):
	def post(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			card_id = request.data.get('card_id')
			if not card_id:
				return Response({'message': 'card_id is required'}, status=status.HTTP_400_BAD_REQUEST)
			card_obj = UserCards.objects.filter(id=card_id).first()
			if not card_obj:
				return Response({'message': 'No card found'}, status=status.HTTP_400_BAD_REQUEST)
			stripe.api_key = settings.STRIPE_SECRET_KEY
			stripe.Customer.delete_source(
				card_obj.the_user_stripe,
				card_obj.card_id
			)
			card_obj.delete()
			return Response({'message': 'Success'})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class bookService(APIView):
	def post(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			booking_id = gernateBookingId()
			sub_service_id = request.data.get('sub_service_id')
			if not sub_service_id:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			sub_service_obj  = SubCategory.objects.get(id=sub_service_id)
			if not sub_service_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'No sub service found'},status=status.HTTP_400_BAD_REQUEST)

			worker_id = request.data.get('worker_id')
			if not worker_id:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Worker id does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			worker_obj  =  User.objects.filter(id = worker_id,is_worker=1).first()
			if not worker_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'No worker found'},status=status.HTTP_400_BAD_REQUEST)

			booking_date = request.data.get('booking_date')
			if not booking_date:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Worker id does not exists.'},status=status.HTTP_400_BAD_REQUEST)

			booking_time = request.data.get('booking_time')
			if not booking_time:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'booking time does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			price = request.data.get('price')
			if not price:
				return Response({'message':'Price is required'},status=status.HTTP_400_BAD_REQUEST)
			
			platform_fees = request.data.get('platform_fees')
			if not platform_fees:
				return Response({'message':'platform_fees is required'},status=status.HTTP_400_BAD_REQUEST)

			admin_commission_fees = request.data.get('admin_commission_fees')
			if not admin_commission_fees:
				return Response({'message':'admin_commission_fees is required'},status=status.HTTP_400_BAD_REQUEST)
			
			total_amount = request.data.get('total_amount')
			if not total_amount:
				return Response({'message':'total_amount is required'},status=status.HTTP_400_BAD_REQUEST)

			book_obj = UserBookings.objects.create(booking_id=booking_id,user=user_obj,worker=worker_obj,booking_date=booking_date,booking_time=booking_time,
							sub_services=sub_service_obj,price=price,platform_fees=platform_fees,admin_commission_fees=admin_commission_fees,total_amount=total_amount)
			return Response({'status_code':status.HTTP_200_OK,'message':'Success','booking_id':book_obj.id})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		
class payBooking(APIView):
	def post(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			booking_id = request.data.get('booking_id')
			if not booking_id:
				return Response({'message': 'booking_id is required'}, status=status.HTTP_400_BAD_REQUEST)
			booking_obj = UserBookings.objects.filter(id=booking_id).first()
			if not booking_obj:
				return Response({'message': 'No booking found'}, status=status.HTTP_400_BAD_REQUEST)
			card_id = request.data.get('card_id')
			if not card_id:
				return Response({'message': 'card_id is required'}, status=status.HTTP_400_BAD_REQUEST)
			card_obj = UserCards.objects.filter(id=card_id,user=user_id).first()
			if not card_obj:
				return Response({'message': 'No card found is required'}, status=status.HTTP_400_BAD_REQUEST)
			thePaymentObj = paymentWithExistingCard(card_obj.the_user_stripe,card_obj.card_id,booking_obj.total_amount)
			if thePaymentObj['status'] == True:
				CustTransaction = UserTranscation.objects.create(transcation_id=generateTranscationsId(),user=user_obj,booking=booking_obj,amount=str(booking_obj.total_amount),txn_id=thePaymentObj['data']['balance_transaction'],recipet_url=thePaymentObj['data']['receipt_url'],payment_mode = thePaymentObj['data']['payment_method_details']['type'],transcation_type="pay")
				booking_obj.is_paid = True
				booking_obj.save()
				
				wallet_obj = ServiceProviderWallet.objects.filter(worker_id = booking_obj.worker_id).first()
				other_amount =   OtherSettings.objects.all().first()
				total_amount = int(booking_obj.price)+ int(other_amount.platform_fee)+int(other_amount.admin_commission)
				wallet_obj.amount += int(total_amount)
				wallet_obj.save()
				
				message = "You got a new booking request"
				server_key = str(settings.FIREBASE_SERVER_KEY)
				registration_id = booking_obj.worker.device_token
				message_title = "Booking Request"
				message_body = message
				extra_notification_kwargs = {
				'image': message
				}
				data_message = {		'type': 'booking_request',
										'title' : 'BOOKING REQUEST',
										"message" : message
									}
				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,extra_notification_kwargs=extra_notification_kwargs)

				return Response({'message': 'Success'})

			else:
				return Response({'message':thePaymentObj['message']},status=status.HTTP_400_BAD_REQUEST)	
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class payBookingWallet(APIView):
	def post(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			booking_id = request.data.get('booking_id')
			if not booking_id:
				return Response({'message': 'booking_id is required'}, status=status.HTTP_400_BAD_REQUEST)
			booking_obj = UserBookings.objects.filter(id=booking_id).first()
			if not booking_obj:
				return Response({'message': 'No booking found'}, status=status.HTTP_400_BAD_REQUEST)
			

			wallet_obj = UserWallet.objects.filter(user = user_obj).first()
			if not wallet_obj:
				return Response({'message': 'No wallet found for this user.'}, status=status.HTTP_400_BAD_REQUEST)
			

			other_amount =   OtherSettings.objects.all().first()
			total_amount = int(booking_obj.price)+ int(other_amount.platform_fee)+int(other_amount.admin_commission)
			if total_amount > int(wallet_obj.amount):
				print('appointment',booking_obj.price)
				print('wallet',wallet_obj.amount)
				return Response({'message': 'You do not have sufficent balance in wallet.'}, status=status.HTTP_400_BAD_REQUEST)
			
			CustTransaction = UserTranscation.objects.create(transcation_id = generateTranscationsId(),user=user_obj,booking=booking_obj,amount=str(total_amount),payment_mode = 'wallet',transcation_type='pay')
			booking_obj.is_paid = True
			booking_obj.save()	
			new_wallet = int(wallet_obj.amount) - int(total_amount)
			wallet_obj.amount = new_wallet
			wallet_obj.save()



			service_wallet_obj = ServiceProviderWallet.objects.filter(worker = booking_obj.worker.id).first()
			
			new_wallet_provider = int(service_wallet_obj.amount) + int(total_amount)
			service_wallet_obj.amount = new_wallet_provider
			service_wallet_obj.save()

			# fortune_wallet_obj = FotuneTellerWallet.objects.filter(fortune_teller=appointment_obj.fortune_teller).first()
			# if fortune_wallet_obj:
			# 	fortune_wallet_obj.amount += appointment_obj.price
			# 	fortune_wallet_obj.save()
			# else:
			# 	FotuneTellerWallet.objects.create(fortune_teller=appointment_obj.fortune_teller,amount=appointment_obj.price)

			# FortuneTellerTranscations.objects.create(transcation_id=generateTranscationsIdFortune(),seer_user=seer_user_obj,fortune_teller=appointment_obj.fortune_teller,amount=appointment_obj.price,payment_mode='wallet',transcation_type="appointment")
			
			return Response({'message': 'Success'})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		


class getMyBookingList(APIView):
	def get(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY,algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj =  User.objects.filter(id = user_id,is_user=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			booking_type = request.GET.get('booking_type')
			if not booking_type:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'booking_type is required'},status=status.HTTP_400_BAD_REQUEST)

			if booking_type == 'upcoming':
				booking_obj = UserBookings.objects.filter(Q(booking_status ='Pending')|Q(booking_status ='Accepted'),user = user_obj,is_paid = True).order_by('-id')
			elif booking_type == 'complete':
				booking_obj = UserBookings.objects.filter(user = user_obj,is_paid = True,booking_status = 'Completed').order_by('-id')
			else:
				booking_obj = UserBookings.objects.filter(user = user_obj,is_paid = True,booking_status = 'Declined').order_by('-id')

			booking_Data = []
			for booking in booking_obj:
				check_rating = ServiceProviderRatingReviews.objects.filter( user = booking.user_id,service_provider = booking.worker_id,booking_id = booking.id)
				if check_rating :
					is_rated = True
				else:
					is_rated = False
				all_data = {
					'id': booking.id,
					'booking_id': booking.booking_id,
					'user_id':booking.user_id,
					'worker_id':booking.worker_id,
					'worker_name':booking.worker.first_name + ' ' + booking.worker.last_name,
					'worker_image':booking.worker.avatar,
					'service_id':booking.sub_services.category_id,
					'service_name':booking.sub_services.category.name,
					'sub_service_id':booking.sub_services_id,
					'sub_service_name':booking.sub_services.name,
					'booking_date':booking.booking_date,
					'booking_time':booking.booking_time,
					'booking_time':booking.booking_time,
					'booking_status':booking.booking_status,
					'booking_completed':booking.booking_completed,
					'price':booking.price,
					'platform_fees':booking.platform_fees,
					'admin_commission_fees':booking.admin_commission_fees,
					'total_amount':booking.total_amount,
					'is_paid':booking.is_paid,
					'is_rated':is_rated,
				}
				booking_Data.append(all_data)
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','data':booking_Data}) 
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class homepage(APIView):
	def get(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			popular_providers  =  User.objects.filter(is_worker =  1,end_date__isnull = True).order_by('-ratings')[:5]
			popular_Providers = []
			for pop in popular_providers:
				popluar_prov = {
					'id': pop.id,
					'name': pop.first_name+" "+pop.last_name,
					'avatar': pop.avatar,
					'ratings': pop.ratings,
				}					
				popular_Providers.append(popluar_prov)

			category_obj_data = Category.objects.filter(end_date__isnull=True)
			service_Data = []
			for cat in category_obj_data:
				service_data_all = {
					'id': cat.id,
					'image': cat.image,
					'name': cat.name,
				}
				service_Data.append(service_data_all)

			featured_service_obj = FetaureService.objects.filter(end_date__isnull=True)
			feature_Data = []
			for feature in featured_service_obj:
				feature_data = {
					'sub_service_id': feature.sub_category.id,
					'sub_service_name': feature.sub_category.name,
					'sub_service_image': feature.sub_category.image,
				}
				feature_Data.append(feature_data)

			banner_obj = BannerManagement.objects.all()
			banner_Data = []
			for banner in banner_obj:
				banner_data = {
					'id':banner.id,
					'banner_title': banner.banner_title,
					'image': banner.image,
					'created_at': banner.start_date,
				}
				banner_Data.append(banner_data)

			return Response({'status_code': status.HTTP_200_OK, 'status_message': 'Success',
							 'service_data': service_Data, 'feature_data': feature_Data,'popular_Providers':popular_Providers,'banner_Data':banner_Data})

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


class CancelBooking(APIView):
	def post(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			booking_id = request.data.get('booking_id')
			if not booking_id:
				return Response({'message': 'booking_id is required'}, status=status.HTTP_404_NOT_FOUND)

			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 = UserBookings.objects.filter(id=booking_id,user = user_obj).first()
			if not appointment_obj:
				return Response({'message': 'Booking not found'}, status=status.HTTP_404_NOT_FOUND)
			worker_obj = User.objects.get(id =  appointment_obj.worker.id)
			appointment_obj.booking_status = 'Declined'
			appointment_obj.cancellation_reason = cancellation_reason
			appointment_obj.cancelled_by = 'user'
			appointment_obj.save()

			wallet_obj = UserWallet.objects.filter(user = user_obj).first()
			other_amount =   OtherSettings.objects.all().first()	

			total_amount = int(appointment_obj.price)+ int(other_amount.platform_fee)+int(other_amount.admin_commission)

			print('appointment',appointment_obj.price)
			print('wallet',wallet_obj.amount)

			CustTransaction = UserTranscation.objects.create(transcation_id = generateTranscationsId(),user=user_obj,booking=appointment_obj,amount=str(total_amount),payment_mode = 'wallet',transcation_type='refund')
			new_wallet = int(wallet_obj.amount) + int(total_amount)
			wallet_obj.amount = new_wallet
			wallet_obj.save()


			service_wallet_obj = ServiceProviderWallet.objects.filter(worker = appointment_obj.worker.id).first()
			new_wallet_provider = int(service_wallet_obj.amount) - int(total_amount)
			service_wallet_obj.amount = new_wallet_provider
			service_wallet_obj.save()



			WorkerNotifications.objects.create(message='The booking id '+appointment_obj.booking_id+' has been cancelled by the user.',type="appointment_booking",worker= worker_obj)
			

			# message = 'The booking id '+appointment_obj.booking_id+' has been cancelled by the user.'
			# server_key = str(settings.FIREBASE_SERVER_KEY)
			# registration_id = worker_obj.device_token
			# message_title = "Booking Cancelled"
			# message_body = message
			# extra_notification_kwargs = {
			# 'image': message
			# }
			# data_message = {		'type': 'booking_declined',
			# 						'title' : 'BOOKING DECLINED',
			# 						"message" : message
			# 					}
			# 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,extra_notification_kwargs=extra_notification_kwargs)
			return Response({'message': 'Success'})
		except Exception as e:
			return Response({'message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class RescheduleBooking(APIView):
	def post(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			
			booking_id = request.data.get('booking_id')
			if not booking_id:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'booking id is required.'},
								status=status.HTTP_400_BAD_REQUEST)
			
			booking_date = request.data.get('booking_date')
			if not booking_date:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Worker id does not exists.'},status=status.HTTP_400_BAD_REQUEST)

			booking_time = request.data.get('booking_time')
			if not booking_time:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'booking time does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			booking_obj =  UserBookings.objects.filter(booking_id=booking_id).first()
			book_obj = UserBookings.objects.filter(booking_id=booking_id).update(booking_date=booking_date,booking_time=booking_time)
			message = str(booking_obj.booking_id) +" has been rescheduled."
			server_key = str(settings.FIREBASE_SERVER_KEY)
			registration_id = booking_obj.worker.device_token
			message_title = "Booking Request"
			message_body = message
			extra_notification_kwargs = {
			'image': message
			}
			data_message = {		'type': 'booking_request',
									'title' : 'BOOKING REQUEST',
									"message" : message
								}
			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,extra_notification_kwargs=extra_notification_kwargs)

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



class RefundRequest(APIView):
	def get(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			booking_id = request.GET.get('booking_id')
			if not booking_id:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'Booking Id is required'},
								status=status.HTTP_400_BAD_REQUEST)
			
			booking_obj = UserBookings.objects.filter(id=booking_id,user = user_obj,booking_status ='Declined').first()
			if not booking_obj:
				return Response({'message': 'No booking found'}, status=status.HTTP_404_NOT_FOUND)
			
			all_data = {
					'id': booking_obj.id,
					'booking_id': booking_obj.booking_id,
					'user_id':booking_obj.user_id,
					'worker_id':booking_obj.worker_id,
					'worker_name':booking_obj.worker.first_name + ' ' + booking_obj.worker.last_name,
					'worker_image':booking_obj.worker.avatar,
					'sub_service_id':booking_obj.sub_services_id,
					'sub_service_name':booking_obj.sub_services.name,
					'booking_date':booking_obj.booking_date,
					'booking_time':booking_obj.booking_time,
					'booking_time':booking_obj.booking_time,
					'booking_status':booking_obj.booking_status,
					'booking_completed':booking_obj.booking_completed,
					'price':booking_obj.price,
					'platform_fees':booking_obj.platform_fees,
					'admin_commission_fees':booking_obj.admin_commission_fees,
					'total_amount':booking_obj.total_amount,
					'is_paid':booking_obj.is_paid,
				}
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','data':all_data}) 
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

	def post(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			booking_id = request.data.get('booking_id')
			if not booking_id:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'Booking Id is required'},
								status=status.HTTP_400_BAD_REQUEST)
			
			booking_obj = UserBookings.objects.filter(id=booking_id,user = user_obj,booking_status ='Declined').first()
			if not booking_obj:
				return Response({'message': 'No booking found'}, status=status.HTTP_404_NOT_FOUND)

			AdminRefundRequest.objects.create(booking = booking_obj , refund_amount = int(booking_obj.price)+int(booking_obj.admin_commission_fees)+int(booking_obj.platform_fees) , date_processed= date.today())
			AdminNotifications.objects.create(message='A new refund request for booking id '+booking_obj.booking_id+' generated.',type="refund_booking")
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success'})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class myWallet(APIView):
	def get(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			wallet_obj = UserWallet.objects.filter(user = user_obj ).first()
			if not wallet_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'No wallet found'},status=status.HTTP_400_BAD_REQUEST)

			wallet_data = {
				'amount': wallet_obj.amount,
			}
			trascation_type = request.GET.get('trascation_type')
			if not trascation_type:
				return Response({'message': 'trascation_type is required'}, status=status.HTTP_404_NOT_FOUND)

			if trascation_type == 'refund':
				trans_obj = UserTranscation.objects.filter(user =  user_obj,payment_mode="wallet",transcation_type = "refund").order_by('-id')[:5]
			elif trascation_type == 'pay':
				trans_obj = UserTranscation.objects.filter(user =  user_obj,payment_mode="wallet",transcation_type = "pay").order_by('-id')[:5]
			else:
				trans_obj = UserTranscation.objects.filter(user =  user_obj,payment_mode="wallet").order_by('-id')[:5]
			Trans_Data = []
			for trans in trans_obj:
				trans_data = {
					'id':trans.id,
					'transcation_id':trans.transcation_id,
					'booking_id':trans.booking.booking_id,
					'amount':trans.amount,
					'transcation_type':trans.transcation_type,
					'created_at':trans.created_at,
				}

				Trans_Data.append(trans_data)
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','wallet_data':wallet_data,'trans_data':Trans_Data})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class addMoneyWallet(APIView):
	def post(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			data = request.data
			amount = data.get('amount')
			if not amount:
				return Response({'message':'amount is required'},status=status.HTTP_400_BAD_REQUEST)
			card_id = request.data.get('card_id')
			if not card_id:
				return Response({'message': 'card_id is required'}, status=status.HTTP_400_BAD_REQUEST) 
			card_obj = UserCards.objects.filter(id=card_id,user=user_obj).first()
			if not card_obj:
				return Response({'message': 'No card found is required'}, status=status.HTTP_400_BAD_REQUEST)
			thePaymentObj = paymentWithExistingCard(card_obj.the_user_stripe,card_obj.card_id,int(amount))
			if thePaymentObj['status'] == True:
				user_wallet = UserWallet.objects.filter(user_id = user_obj.id).first()

				if user_wallet:
					user_wallet.amount += int(amount)
					user_wallet.save()
				else:
					UserWallet.objects.create(
						user=user_obj,
						amount=amount
					)
			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 viewAllWalletTransactions(APIView):
	def get(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			trascation_type = request.GET.get('trascation_type')
			if not trascation_type:
				return Response({'message': 'trascation_type is required'}, status=status.HTTP_404_NOT_FOUND)

			if trascation_type == 'refund':
				trans_obj = UserTranscation.objects.filter(user =  user_obj,payment_mode="wallet",transcation_type = "refund").order_by('-id')
			elif trascation_type == 'pay':
				trans_obj = UserTranscation.objects.filter(user =  user_obj,payment_mode="wallet",transcation_type = "pay").order_by('-id')
			else:
				trans_obj = UserTranscation.objects.filter(user =  user_obj,payment_mode="wallet").order_by('-id')
			Trans_Data = []
			for trans in trans_obj:
				trans_data = {
					'id':trans.trans_id,
					'transcation_id':trans.transcation_id,
					'booking_id':trans.booking.booking_id,
					'amount':trans.amount,
					'transcation_type':trans.transcation_type,
					'created_at':trans.created_at,
				}

				Trans_Data.append(trans_data)
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','trans_data':Trans_Data})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class addRatingReviewServiceProvider(APIView):
	def post(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')
			serviceprovider_id = request.data.get('serviceprovider_id')
			if not serviceprovider_id:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'service provider id required'})
			
			provider_obj  = User.objects.filter(id =  serviceprovider_id,is_worker = 1).first() 
			if not provider_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'No service provider found'})

			rating = request.data.get('rating')
			if not rating:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'rating id required'})

			review = request.data.get('review')
			if not review:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'review id required'})
			booking_id = request.data.get('booking_id')
			if not booking_id:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'booking_id is required'})
			booking_obj = UserBookings.objects.get(id = booking_id)
			ServiceProviderRatingReviews.objects.create(rating = rating,review=review,service_provider=provider_obj,user = user_obj,booking = booking_obj )
			total_count = ServiceProviderRatingReviews.objects.filter(service_provider=provider_obj).count()
			all_rating = [float(provider_obj.rating) for provider_obj in ServiceProviderRatingReviews.objects.filter(service_provider=provider_obj)]
			final_rating = sum(all_rating)
			average=float(final_rating)/float(total_count)
			provider_obj.ratings = average
			provider_obj.save()

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

class deleteRatingReviewServiceProvider(APIView):
	def post(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			review_id = request.data.get('review_id')
			if not review_id:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'review id required'})

			review_obj  = ServiceProviderRatingReviews.objects.get(id=review_id,user_id = user_obj.id).first()
			if not review_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'review not found'})
			review_obj.delete()
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success'})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		


class createConverstationUser(APIView):
	def post(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			service_provider_id = request.data.get('service_provider_id')
			if not service_provider_id:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'service provider id is required.'})
			
			service_provider_obj = User.objects.filter(id=service_provider_id,is_worker = 1,end_date__isnull = True).first()
			if not service_provider_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'No service provider found'})
			
			booking_id = request.data.get('booking_id')
			if not booking_id:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'Booking id is required'})

			book_obj = UserBookings.objects.get(id=booking_id)
			if not book_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'Booking not found'})

			# Check if conversation already exists
			existing_conversation = Conversation.objects.filter(service_provider=service_provider_obj, user=user_obj).first()
			if existing_conversation:
				twilio_channel_sid = existing_conversation.twilio_channel_sid
			else:
				concatinate_names= str(service_provider_obj.first_name) + str(user_obj.first_name) + str(user_obj.id) + str(service_provider_obj.id)
				suffle_string = list(concatinate_names)
				random.shuffle(suffle_string)
				conversation_name = ''.join(suffle_string)
				# Create Conversation chat
				conversation = client.conversations \
						.v1 \
						.conversations \
						.create(friendly_name=conversation_name)
				

				conversation_obj = Conversation.objects.create(service_provider=service_provider_obj,user=user_obj,booking = book_obj )
				conversation_obj.twilio_channel_sid = conversation.sid
				conversation_obj.last_message = datetime.now()
				conversation_obj.save()

				user_attributes= {"id":str(user_obj.id),"name":str(user_obj.first_name)+' '+str(user_obj.last_name),
					"image":str(user_obj.avatar)
				}
				user_json_attributes = json.dumps(user_attributes)

				user_participant = client.conversations \
					.v1 \
					.conversations(conversation.sid) \
					.participants \
					.create(identity=str(user_obj.id),attributes=user_json_attributes)
				

				service_provider_attributes= {"id":str(service_provider_obj.id),"name":str(service_provider_obj.first_name)+' '+str(service_provider_obj.last_name),
					"image":str(service_provider_obj.avatar)
				}
				service_provider_json_attributes = json.dumps(service_provider_attributes)

				service_provider_participant = client.conversations \
					.v1 \
					.conversations(conversation.sid) \
					.participants \
					.create(identity=str(service_provider_obj.id),attributes=service_provider_json_attributes)



				conversation_obj.user_twilio_id = user_participant.sid
				conversation_obj.service_provider_twilio_id = service_provider_participant.sid
				conversation_obj.save()

				twilio_channel_sid = conversation_obj.twilio_channel_sid


			return Response ({'status_code':status.HTTP_200_OK,'status_message':'success','twilio_channel_sid':twilio_channel_sid})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		


class createToken(APIView):
	def post(self, request):
		try:
			user_id = request.data.get('user_id')
			if not user_id:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'user id is required'})
			
			user_obj = User.objects.get(id=user_id)
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'No account found'})
			
			identity = user_obj.id
			token = AccessToken(account_sid,api_sid,api_secret,identity=identity)

			if chat_service_sid:
				chat_grant = ChatGrant(service_sid=chat_service_sid)
				token.add_grant(chat_grant)

			notification = client.conversations \
			.v1 \
			.services(chat_service_sid) \
			.configuration \
			.notifications() \
			.update(
				new_message_enabled=True,
				new_message_sound='default',
				new_message_template="You have a new message in ${CONVERSATION}: ${MESSAGE}"
			)

			alldata = {
			'identity':identity,
			'token':token.to_jwt(),
			}
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Token Created Successfully','data':alldata})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


class userConverstationListing(APIView):
	def get(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			conversations = Conversation.objects.filter(user = user_obj )
			
			conversation_list = []
			for conversation in conversations:
				messages = client.conversations \
				  .v1 \
				  .conversations(conversation.twilio_channel_sid) \
				  .messages \
				  .list(order='desc', limit=1)
				last_message = ''
				time = ''
				message_date = ''
				for record in messages:
					if record.body:
						last_message = record.body 
						time = timesince(record.date_created)+' ago'
						message_date = record.date_created
					elif record.media:
						
						last_message = 'file'
						time = timesince(record.date_created)+' ago'
						message_date = record.date_created
				
				conversation_data = {
					"id": conversation.id,
					"twilio_channel_sid": conversation.twilio_channel_sid,
					"customer_name": conversation.user.first_name + ' ' + conversation.user.last_name,
					"customer_image": conversation.user.avatar,
					"customer_id":conversation.user.id,
					"service_provider_name": conversation.service_provider.first_name + ' ' + conversation.service_provider.last_name,
					"service_provider_image": conversation.service_provider.avatar,
					"service_provider_id": conversation.service_provider.id,
					"booking_id": conversation.booking.id,
					"booking_status": conversation.booking.booking_status,
					"booking_completed":conversation.booking.booking_completed,
					"last_message":last_message,
					"time":time,
					"message_date":message_date,
				}
				conversation_list.append(conversation_data)
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'success','data':conversation_list})	
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class enableCustomerNotifications(APIView):
	def get(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			notification_setting = user_obj.notification_enable
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'success','notification_setting':notification_setting})	
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

	def post(self,request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			notification_setting = request.data.get('notification_setting')
			if not notification_setting:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'notification setting is required'}),
		
			user_obj.notification_enable = notification_setting
			user_obj.save()
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'success','notification_setting':notification_setting})	
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class approvalPendingWorkList(APIView):
	def get(self, request):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')			
			approval_obj  = UserBookings.objects.filter(booking_status = 'Approval_Pending',user = user_obj)

			all_Data = []
			for approve in approval_obj:
				check_rating = ServiceProviderRatingReviews.objects.filter( user = approve.user_id,service_provider = approve.worker_id)
				if check_rating :
					is_rated = True
				else:
					is_rated = False
				all_data = {
					'id': approve.id,
					'booking_id': approve.booking_id,
					'user_id':approve.user_id,
					'worker_id':approve.worker_id,
					'worker_name':approve.worker.first_name + ' ' + approve.worker.last_name,
					'worker_image':approve.worker.avatar,
					'sub_service_id':approve.sub_services_id,
					'sub_service_name':approve.sub_services.name,
					'booking_date':approve.booking_date,
					'booking_time':approve.booking_time,
					'booking_status':approve.booking_status,
					'price':approve.price,
					'is_rated':is_rated
				}
				all_Data.append(all_data)
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','data':all_Data})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class approvalPendingWorkDetails(APIView):
	def get(self, request, *args, **kwargs):
		try:
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')					
			booking_id = request.GET.get('booking_id')
			if not booking_id:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'booking_id is required.'},
				status=status.HTTP_400_BAD_REQUEST)
		

			booking_obj = UserBookings.objects.filter(id = booking_id, user =user_obj,booking_status = 'Approval_Pending')
			if not booking_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'booking not found'},
				status=status.HTTP_400_BAD_REQUEST)
			all_Data = []
			for approve in booking_obj:
				all_data = {
						'id': approve.id,
						'booking_id': approve.booking_id,
						'user_id':approve.user_id,
						'worker_id':approve.worker_id,
						'worker_name':approve.worker.first_name + ' ' + approve.worker.last_name,
						'worker_image':approve.worker.avatar,
						'sub_service_id':approve.sub_services_id,
						'sub_service_name':approve.sub_services.name,
						'booking_date':approve.booking_date,
						'booking_time':approve.booking_time,
						'booking_time':approve.booking_time,
						'booking_status':approve.booking_status,
						'booking_completed':approve.booking_completed,
						'price':approve.price,
						'is_paid':approve.is_paid,
						'complete_image':approve.complete_image,
					}
				all_Data.append(all_data)

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


class approvedDisapproveWork(APIView):
	def post(self, request):
			token = get_authorization_header(request)
			if token is None or token == "null" or token.strip() == "":
				raise exceptions.AuthenticationFailed('Authorization Header or Token is missing on Request Headers')
			decoded = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
			user_id = decoded['user_id']
			user_obj = User.objects.filter(id=user_id, is_user=1).first()
			if not user_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'User does not exist.'},
								status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')		
			final_status = request.data.get('final_status')
			if not final_status:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'final_status is required'},
								status=status.HTTP_400_BAD_REQUEST)
			

			booking_id = request.data.get('booking_id')
			if not booking_id:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'booking_id is required'},
				status=status.HTTP_400_BAD_REQUEST)

			booking_obj  =  UserBookings.objects.filter(id = booking_id, user =user_obj,booking_status = 'Approval_Pending').first()
			if not booking_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'booking not found'},
				status=status.HTTP_400_BAD_REQUEST)

			if final_status == 'approved':
				worker_obj = User.objects.get(id = booking_obj.worker.id)
				booking_obj.booking_status = 'Completed'
				booking_obj.save()
				message = "Your booking completion is approved successfully by the customer"
				server_key = str(settings.FIREBASE_SERVER_KEY)
				registration_id = booking_obj.worker.device_token
				message_title = "Booking Completion Approved"
				message_body = message
				extra_notification_kwargs = {
				'image': message
				}
				data_message = {		'type': 'booking_completed_approved',
										'title' : 'BOOKING COMPLETED APPROVED',
										"message" : message
									}
				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,extra_notification_kwargs=extra_notification_kwargs)
				WorkerNotifications.objects.create(message='The booking id '+booking_obj.booking_id+' has been approved successfully by the user.',type="appointment_booking",worker= worker_obj)

			else:
				worker_obj = User.objects.get(id = booking_obj.worker.id)
				booking_obj.booking_status = 'Pending'
				booking_obj.save()
				message = "Your booking completion is disapproved by the customer"
				server_key = str(settings.FIREBASE_SERVER_KEY)
				registration_id = booking_obj.worker.device_token
				message_title = "Booking Completion Disapproved"
				message_body = message
				extra_notification_kwargs = {
				'image': message
				}
				data_message = {		'type': 'booking_completed_disapproved',
										'title' : 'BOOKING COMPLETED DISAPPROVED',
										"message" : message
									}
				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,extra_notification_kwargs=extra_notification_kwargs)
				WorkerNotifications.objects.create(message='The booking id '+booking_obj.booking_id+' has been disapproved by the user.',type="appointment_booking",worker= worker_obj)

			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success'})	

	