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
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
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 worker_panel.models import *
from pyfcm import FCMNotification
from twilio.jwt.access_token.grants import (
	SyncGrant,
	ChatGrant,
	VideoGrant
)
from twilio.rest import Client
from twilio.jwt.access_token import AccessToken
import ast




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 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'


def gernatePayoutId():
	lastObj= ServiceProviderPayoutTranscation.objects.all().last()
	if lastObj:
		if not lastObj.transcation_id:
			return 'POUT0001'

		theId=lastObj.transcation_id
		theId=theId[4:]
		theId=int(theId)+1
		theId=str(theId)
		theId=theId.zfill(4)
		return "POUT"+str(theId)
	else:
		return 'POUT0001'

class workerRegister(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_worker = True)
			ran_num = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(12)])
			baselink =  '/api-worker/worker-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('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)
			from datetime import date
			today = date.today()
			subject = 'New Worker Registered'
			html_message = render_to_string('new_worker_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 workerEmailVerification(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.save()
			ServiceProviderWallet.objects.create(worker = user_obj,amount = 0)
			AdminNotifications.objects.create(message = "A new service provider "+user_obj.first_name+" "+user_obj.last_name+" has been registered successfully",type="new_service_provider")
			return render(request,'email_verified_success.html')	
		except Exception as e:
			print(e)
			return render(request,'email_verified_unsuccess.html')	


class workerLogin(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).count()
			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)
	
			check_verification =  User.objects.filter(email=email,is_email_verified = False,is_worker=1).first()
			if check_verification:
				ran_num = ''.join([random.choice(string.ascii_letters + string.digits) for n in range(12)])
				baselink =  '/api-worker/worker-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_worker = True).first()
			if not userObj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'No account found'},status=status.HTTP_400_BAD_REQUEST)
			if userObj.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 userObj.end_date is not None:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'This account is deleted.Please contact superadmin.'},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={'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),
					'is_profile_completed':userObj.is_profile_completed,
					'is_email_verified':userObj.is_email_verified,
				   }
				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 getCategoryList(APIView):
	def get(self, request):
		try:
			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 getSubServiceList(APIView):
	def get(self, request):
		try:
			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)
			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)
			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 workerUpdateProfile(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_worker=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Worker does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')	
			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,
				'experience':user_obj.experience,
				'address':user_obj.address,
				'phone_number':user_obj.phone_number,
				'is_profile_completed':user_obj.is_profile_completed,
				'bank_details_filled':user_obj.bank_details_filled,
				'is_otp_verified':user_obj.is_otp_verified,
			}

			service_obj = WorkerServices.objects.filter(worker = user_obj.id )

			service_Data = []
			for service in service_obj:
				service_data = {
					'id':service.id,
					'service_name':service.services.name,
					'sub_service_name':service.sub_services.name,
					'service_id':service.services.id,
					'sub_service_id':service.sub_services.id,
					'price':service.price,
					'time_taken':service.time_taken,

				}
				service_Data.append(service_data)
			
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Success','data':all_data,'service':service_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_worker=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Worker 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)
			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)
			experience = request.data.get('experience')
			if not experience:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'experience 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)
			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)
			check_phone = User.objects.filter(phone_number = phone_number).exclude(id=user_obj.id)
			if check_phone:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'This phone number is already associated with some account.'},status=status.HTTP_400_BAD_REQUEST)
			sub_services = request.data.get('sub_services')
			if sub_services:
				sub_services_list = json.loads(sub_services)
				all_worker_service = WorkerServices.objects.filter(worker = user_obj)
				if all_worker_service:
					for service in all_worker_service:
						service.delete()
				
				for service in sub_services_list:
					ser_id = int(service.get("id"))
					cat_obj = SubCategory.objects.get(id = ser_id)
					main_obj = Category.objects.get(id = cat_obj.category.id)
					WorkerServices.objects.create(worker=user_obj,services= main_obj,sub_services=cat_obj)

			avatar = request.data.get('avatar')
			is_profile_completed = request.data.get('is_profile_completed')
			user_obj.first_name = first_name
			user_obj.last_name = last_name
			user_obj.email = email
			user_obj.address = address
			user_obj.experience = experience
			user_obj.phone_number = phone_number
			user_obj.is_profile_completed = is_profile_completed
			if avatar:
				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,
				'experience':user_obj.experience,
				'address':user_obj.address,
				'phone_number':user_obj.phone_number,
			}

			service_obj = WorkerServices.objects.filter(worker = user_obj.id )

			service_Data = []
			for service in service_obj:
				service_data = {
					'id':service.id,
					'service_id':service.services.id,
					'sub_service_id':service.sub_services.id,

				}
				service_Data.append(service_data)

			return Response({'status_code':status.HTTP_200_OK,'status_message':'Profile updated successfully','data':all_data,'service':service_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_worker=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Worker 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 workerChangePassword(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_worker=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)
			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 UploadImages(APIView):
	def post(self, request):
		try:
			data = request.data
			images = data.getlist('images')
			image_urls = []
			for image in images:
				image_path = uploadTheImages(image)
				image_urls.append(image_path)
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Success','data':image_urls})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class uploadWorkImage(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_worker=1).first()
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')	
			prvs_obj = WorkerWorkImages.objects.filter(worker_id = user_id)
			all_Data = []
			for image in prvs_obj:
				all_data = {
					'id':image.id,
					'image':image.image
				}
				all_Data.append(all_data)
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Uploaded successfully','all_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_worker=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')				
			images =request.data.get('images')
			WorkerWorkImages.objects.create(worker=user_obj,image=images)
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Uploaded 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 deleteWorkImage(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_worker=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)
			image_id  =  request.data.get('image_id')
			if not image_id:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'image_id is required'},status=status.HTTP_400_BAD_REQUEST)
			work_img =  WorkerWorkImages.objects.get(id = image_id)
			work_img.delete()
			return Response({'status_code':status.HTTP_200_OK,'status_message':'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 addWorkerTimeSlots(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_worker=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')	
			check_slots = WorkerTimeSlots.objects.filter(worker = user_obj).first()
			if check_slots:
				product_images =  ast.literal_eval(check_slots.slots)
				all_data = {
					   'id':check_slots.id,
					   'worker_id': check_slots.worker_id,
					   'time_slots': product_images,
				}
			else:
				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)


	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_worker=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')	
			time_slot =  request.data.get('time_slot')
			if not time_slot:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Time solt is required'},status=status.HTTP_400_BAD_REQUEST)

			check_slots = WorkerTimeSlots.objects.filter(worker = user_obj).first()
			if check_slots:
				WorkerTimeSlots.objects.filter(worker = user_obj).update(slots=time_slot)
			else:
				WorkerTimeSlots.objects.create(worker = user_obj,slots=time_slot)
			return Response({'status_code':status.HTTP_200_OK,'status_message':'Success'}) 
		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 workerDeleteAccount(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_worker=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Service provider 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.now()
			user_obj.save()

			help_support_obj = HelpSupport.objects.filter(user = user_obj.id )
			for help in help_support_obj:
				help.end_date = datetime.now()
				help.save()

			service_obj = WorkerServices.objects.filter(worker = user_obj.id )
			for service in service_obj:
				service.end_date = datetime.now()
				service.save()

			chat_obj = Conversation.objects.filter(service_provider = user_obj.id)
			for chat in chat_obj:
				chat.end_date = datetime.now()
				chat.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 getMyServiceList(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_worker=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Service provider does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')				
			service_obj = WorkerServices.objects.filter(worker = user_obj.id)
			all_Data = []
			for service in service_obj:
				all_data = {
					'id':service.id,
					'service_id':service.services_id,
					'service_name':service.services.name,
					'sub_service_id':service.sub_services_id,
					'sub_service_name':service.sub_services.name,
					'price':service.price,
					'time_taken':service.time_taken,

				}
				all_Data.append(all_data)
			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)

	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_worker=1).first()
			if not user_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Service provider does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			if user_obj.status == 0:
				raise exceptions.AuthenticationFailed('Signature has expired')				
			service_id =  request.data.get('service_id')
			if not service_id:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Service id is required'},status=status.HTTP_400_BAD_REQUEST)
			price = request.data.get('price')
			if not price:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Price is required'},status=status.HTTP_400_BAD_REQUEST)
			time_taken = request.data.get('time_taken')
			if not time_taken:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Time taken is required'},status=status.HTTP_400_BAD_REQUEST)

			WorkerServices.objects.filter(sub_services_id = service_id,worker_id = user_obj.id).update(price=price,time_taken=time_taken)
			return Response({'status_code':status.HTTP_200_OK,'status_message':'success'})

		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 getWorkerNotifications(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_worker=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 = WorkerNotifications.objects.filter(worker=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 deleteWorkerNotifications(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_worker=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)
		WorkerNotifications.objects.filter(id=notification_id).update(end_date=datetime.now())
		return Response({'status_code':status.HTTP_200_OK,'status_message':'Notification Deleted Successfully'})




class getWorkerBookingRequest(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_worker=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_obj = UserBookings.objects.filter(is_paid = True,booking_status ='Pending',worker_id = user_obj )
			booking_Data = []
			for booking in booking_obj:
				all_data = {
					'id': booking.id,
					'booking_id': booking.booking_id,
					'user_id':booking.user_id,
					'user_name':booking.user.first_name + ' ' + booking.user.last_name,
					'user_image':booking.user.avatar,
					'user_address':booking.user.address,
					'worker_id':booking.worker_id,
					'worker_name':booking.worker.first_name + ' ' + booking.worker.last_name,
					'worker_image':booking.worker.avatar,
					'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,
				}
				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({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class workerBookingDetails(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_worker=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 = self.request.query_params.get('booking_id') 
			if not booking_id:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'User does not exists.'},status=status.HTTP_400_BAD_REQUEST)
			booking_obj = UserBookings.objects.filter(id=booking_id,is_paid = True,booking_status ='Pending',worker_id = user_obj ).first()
			if not booking_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'No booking found'},status=status.HTTP_400_BAD_REQUEST)
			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({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class acceptDeclineBooking(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_worker=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')	
			data = request.data
			booking_id = data.get('booking_id')
			status_type = data.get('status_type')
			if not booking_id:
				return Response({'message':'booking id  is required'},status=status.HTTP_400_BAD_REQUEST)
			if not status_type:
				return Response({'message':'status_type is required'},status=status.HTTP_400_BAD_REQUEST)
			if status_type == 'Accepted' or status_type == 'Declined':
				if status_type == "Accepted":
					appointment_obj = UserBookings.objects.filter(id=booking_id,worker_id=user_obj).first()
					if not appointment_obj:
						return Response({'message': 'Booking not found'}, status=status.HTTP_404_NOT_FOUND)
					appointment_obj.booking_status = status_type
					appointment_obj.save()
					

					cust_obj  =  User.objects.filter(id=appointment_obj.user.id).first()
					CustomerNotifications.objects.create(message='Your booking '+appointment_obj.booking_id+' has been accepted successfully.',type="appointment_booking",customer= cust_obj)
					message = "Your booking has been accepted"
					server_key = str(settings.FIREBASE_SERVER_KEY)
					registration_id = cust_obj.device_token
					message_title = "Booking Accepted"
					message_body = message
					extra_notification_kwargs = {
					'image': message
					}
					data_message = {		'type': 'booking_accepted',
											'title' : 'BOOKING ACCEPTED',
											"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)

				else:
					appointment_obj = UserBookings.objects.filter(id=booking_id,worker_id=user_obj).first()
					cust_obj  =  User.objects.filter(id=appointment_obj.user.id).first()
					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,worker_id=user_obj).first()
					if not appointment_obj:
						return Response({'message': 'Booking not found'}, status=status.HTTP_404_NOT_FOUND)
					
					appointment_obj.booking_status = status_type
					appointment_obj.cancellation_reason = cancellation_reason
					appointment_obj.cancelled_by = 'service_provider'
					appointment_obj.save()
					
					CustomerNotifications.objects.create(message='Your booking '+appointment_obj.booking_id+' has been declined.Please check your wallet for refund.',type="appointment_booking",customer= cust_obj)
					message = "Your booking has been declined"
					server_key = str(settings.FIREBASE_SERVER_KEY)
					registration_id = cust_obj.device_token
					message_title = "Booking Declined"
					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)
					other_amount =   OtherSettings.objects.all().first()	
					total_amount = int(appointment_obj.price)+ int(other_amount.platform_fee)+int(other_amount.admin_commission)
					service_wallet_obj = ServiceProviderWallet.objects.filter(worker = user_obj.id).first()
					print('service_wallet_obj',service_wallet_obj.amount)
					if total_amount > int(service_wallet_obj.amount):
						return Response({'message': 'You do not have sufficent balance in wallet for refund for service cancel.'}, status=status.HTTP_400_BAD_REQUEST)
					
					new_wallet_provider = int(service_wallet_obj.amount) - int(total_amount)
					print('new_wallet_provider',new_wallet_provider)
					service_wallet_obj.amount = new_wallet_provider
					service_wallet_obj.save()
					
					wallet_obj = UserWallet.objects.filter(user = cust_obj.id).first()
					print('total_amount',total_amount)
					print('wallet',wallet_obj.amount)

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

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


class getWorkerBookingList(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_worker=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(worker_id = user_obj,is_paid = True,booking_status ='Accepted')
			elif booking_type == 'complete':
				booking_obj = UserBookings.objects.filter(worker_id = user_obj,is_paid = True,booking_status = 'Completed')
			else:
				booking_obj = UserBookings.objects.filter(worker_id = user_obj,is_paid = True,booking_status = 'Declined')
			
			booking_Data = []
			for booking in booking_obj:
				all_data = {
					'id': booking.id,
					'booking_id': booking.booking_id,
					'user_id':booking.user_id,
					'user_name':booking.user.first_name + ' ' + booking.user.last_name,
					'user_image':booking.user.avatar,
					'user_address':booking.user.address,
					'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,
				}
				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({'status_code':status.HTTP_500_INTERNAL_SERVER_ERROR,'status_message':str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class myRatingReviewListing(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_worker=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')	
			
			review_obj = ServiceProviderRatingReviews.objects.filter(service_provider = user_obj.id)
			all_Data = []
			for review in review_obj:
				all_data = {
					'id': review.id,
					'rating':review.rating,
					'review':review.review,
					'customer_name':review.user.first_name+' '+review.user.last_name,
					'booking_id':review.booking.booking_id,
					'customer_avatar':review.user.avatar,
					'created_at':review.start_date,
				}
				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 myRatingReviewDetails(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_worker=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')	
			review_id = request.GET.get('review_id')
			if not review_id:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'review_id is required'},status=status.HTTP_400_BAD_REQUEST)
			review_obj = ServiceProviderRatingReviews.objects.filter(id = review_id,service_provider = user_obj.id).first()
			if not review_obj:
				return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'No review found'},status=status.HTTP_400_BAD_REQUEST)

			all_data = {
					'id': review_obj.id,
					'rating':review_obj.rating,
					'review':review_obj.review,
					'customer_name':review_obj.user.first_name+' '+review_obj.user.last_name,
					'booking_id':review_obj.booking.booking_id,

					'customer_avatar':review_obj.user.avatar,
					'created_at':review_obj.start_date,
				}
			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 createConverstationProvider(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_worker=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')				
			customer_id = request.data.get('customer_id')
			if not customer_id:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'service provider id is required.'})
			
			customer_obj = User.objects.filter(id=customer_id,is_user = 1,end_date__isnull = True).first()
			if not customer_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'No customer 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=user_obj, user=customer_obj).first()
			if existing_conversation:
				twilio_channel_sid = existing_conversation.twilio_channel_sid
			else:
				concatinate_names= str(customer_obj.first_name) + str(user_obj.first_name) + str(user_obj.id) + str(customer_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=user_obj,user=customer_obj,booking =book_obj)
				conversation_obj.twilio_channel_sid = conversation.sid
				conversation_obj.last_message = datetime.now()
				conversation_obj.save()

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

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

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

				service_provider_participant = client.conversations \
					.v1 \
					.conversations(conversation.sid) \
					.participants \
					.create(identity=str(user_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 = service_provider_participant.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 serviceProviderConverstationListing(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_worker=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(service_provider = 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_id": conversation.user.id,
					"customer_name": conversation.user.first_name + ' ' + conversation.user.last_name,
					"customer_image": conversation.user.avatar,
					"service_provider_id": conversation.service_provider.id,
					"service_provider_name": conversation.service_provider.first_name + ' ' + conversation.service_provider.last_name,
					"service_provider_image": conversation.service_provider.avatar,
					"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 enableServiceProviderNotifications(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_worker=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({'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_worker=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({'message':'success','notification_setting':notification_setting})
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		


class markCompleteBooking(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_worker=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({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'booking_id is required'}),
	
			complete_image = request.data.get('complete_image')
			if not complete_image:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'booking_id is required'}),

			booking_obj = UserBookings.objects.get(id= booking_id)
			booking_obj.booking_completed = True
			booking_obj.complete_image = complete_image
			booking_obj.booking_status = "Approval_Pending"
			booking_obj.save()

			WorkerWorkImages.objects.create(worker = user_obj,image = complete_image)
			customer_obj = User.objects.get(id  = booking_obj.user.id)
			CustomerNotifications.objects.create(message='Your booking '+booking_obj.booking_id+' has been completed succesfully.Please check and approve the work.',type="appointment_booking",customer= customer_obj)
			message = "Your booking has been completed succesfully.Please check and approve the work."
			server_key = str(settings.FIREBASE_SERVER_KEY)
			registration_id = customer_obj.device_token
			message_title = "Booking Completed"
			message_body = message
			extra_notification_kwargs = {
			'image': message
			}
			data_message = {		'type': 'booking_completed',
									'title' : 'BOOKING COMPLETED',
									"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 pendingApprovalWorks(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_worker=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_obj = UserBookings.objects.filter(worker_id = user_obj,booking_status ='Approval_Pending')

			booking_Data = []
			for booking in booking_obj:
				all_data = {
					'id': booking.id,
					'booking_id': booking.booking_id,
					'user_id':booking.user_id,
					'user_name':booking.user.first_name + ' ' + booking.user.last_name,
					'user_image':booking.user.avatar,
					'user_address':booking.user.address,
					'worker_id':booking.worker_id,
					'worker_name':booking.worker.first_name + ' ' + booking.worker.last_name,
					'worker_image':booking.worker.avatar,
					'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_status':booking.booking_status,
					'price':booking.price,
					'platform_fees':booking.platform_fees,
					'admin_commission_fees':booking.admin_commission_fees,
					'total_amount':booking.total_amount,
				}
				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 pendingApprovalWorksDetails(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_worker=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,
						'platform_fees':approve.platform_fees,
						'admin_commission_fees':approve.admin_commission_fees,
						'total_amount':approve.total_amount,
						'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 workerBankAccounts(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_worker=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')	
			account_obj  =  WorkerBankAccountDetails.objects.filter(worker = user_obj.id).first()
			if not account_obj:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'No bank account details found'},
								status=status.HTTP_400_BAD_REQUEST)
			
			all_data = {
				'id': account_obj.id,
				'bank': account_obj.bank,
				'sort_code': account_obj.sort_code,
				'account_number': account_obj.account_number,

			}
			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_worker=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')				
			bank = request.data.get('bank')
			if not bank:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'bank is required.'},
				status=status.HTTP_400_BAD_REQUEST)
			sort_code = request.data.get('sort_code')
			if not sort_code:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'sort_code is required.'},
				status=status.HTTP_400_BAD_REQUEST)
			account_number = request.data.get('account_number')
			if not account_number:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'account_number is required.'},
				status=status.HTTP_400_BAD_REQUEST)
			check_account =  WorkerBankAccountDetails.objects.filter(worker = user_obj.id).first()
			if check_account:
				WorkerBankAccountDetails.objects.filter(worker = user_obj.id).update(bank=bank,sort_code=sort_code,account_number=account_number,
					
				)
			else:
				WorkerBankAccountDetails.objects.create(
					worker = user_obj,bank=bank,sort_code=sort_code,account_number=account_number
				)
				user_obj.bank_details_filled = True
				user_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 serviceProviderWallet(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_worker=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')				
			wallet_amount = ServiceProviderWallet.objects.filter(worker = user_obj.id).first()
			transcation_type = request.GET.get('transcation_type')
			payout_Data = []
			recived_Data = []
			if transcation_type == 'payout':
				payout_transcations = ServiceProviderPayoutTranscation.objects.filter(user = user_obj.id).order_by('-id')
				for payout in payout_transcations:
					payout_data = {
						'id':payout.id,
						'transcation_id':payout.transcation_id,
						'amount':payout.amount,
						'transcation_status':payout.transcation_status,
						'created_at':payout.created_at,
					}
					payout_Data.append(payout_data)
			else:
				recived_payments = UserTranscation.objects.filter(booking__worker_id = user_obj.id,transcation_type='pay').order_by('-id')
				for rec in recived_payments:
					recived_data = {
						'id': rec.id,
						'transcation_id': rec.transcation_id,
						'amount': rec.amount,
						'created_at': rec.created_at
					}
					recived_Data.append(recived_data)
			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Success','wallet_amount':wallet_amount.amount,'payout_Data':payout_Data,'recived_Data':recived_Data})	
		except Exception as e:
			return Response({'message': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

class requestPayout(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_worker=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')				
			payout_amount = request.data.get('payout_amount')
			if not payout_amount:
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'payout amount is required.'},
				status=status.HTTP_400_BAD_REQUEST)
			
			provider_wallet =  ServiceProviderWallet.objects.get(worker =  user_obj)
			if int(provider_wallet.amount) < int(payout_amount):
				return Response({'status_code': status.HTTP_400_BAD_REQUEST, 'status_message': 'You do not have sufficient funds'},
				status=status.HTTP_400_BAD_REQUEST)
			
			else:
				new_amount = int(provider_wallet.amount) - int(payout_amount)
				provider_wallet.amount =  int(new_amount)
				provider_wallet.save()
				payout_id =  gernatePayoutId()
				ServiceProviderPayoutTranscation.objects.create(transcation_id = payout_id,user = user_obj,amount = payout_amount,transcation_status = "Pending")

			return Response ({'status_code':status.HTTP_200_OK,'status_message':'Request send successfully'})	

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