from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from datetime import datetime
from django.conf import settings
from twilio.jwt.access_token.grants import (
	SyncGrant,
	ChatGrant,
	VideoGrant
)
from twilio.rest import Client
from twilio.jwt.access_token import AccessToken
from fortune_teller.authentication import authenticated, seerauthenticated
from seer_user.models import SeerUser, SeerUserNotifications, FortuneAppointmentBook
from fortune_teller.models import FortuneTeller, FotuneTellerWallet, FortuneTellerTranscations,FortuneTellerNotifications
from .models import *
import random
from datetime import datetime, timedelta
import json
from django.utils.timesince import timesince
from django.db.models import Q,Count
from pyfcm import FCMNotification
from admin_panel.models import GeneralSettings
import pytz
from admin_panel.functions import TransferToConnectedAccount
from django.template.loader import render_to_string
from django.contrib import messages
from django.core import mail
# Create your views here.


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

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


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)

'''=============== Conversation between User and fortune teller API ==============='''
class CreateConversation(APIView):
	def post(self,request):
		try:
			try:
				uid = authenticated(request)
			except Exception as e:
				return Response({'message': str(e)}, status=status.HTTP_401_UNAUTHORIZED)

			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			data = request.data
			seer_user_id = data.get('seer_id')
			appointment_id = data.get('appointment_id')
			if not seer_user_id:
				return Response({'message': 'seer_id is  required'}, status=status.HTTP_400_BAD_REQUEST)
			if not appointment_id:
				return Response({'message': 'appointment_id is  required'}, status=status.HTTP_400_BAD_REQUEST)
			# Get seer user
			seer_user = SeerUser.objects.filter(id=seer_user_id).first()
			appointment_obj = FortuneAppointmentBook.objects.filter(id=appointment_id).first()
			if not seer_user:
				return Response({'message': 'Seer User not found'}, status=status.HTTP_404_NOT_FOUND)
			if not appointment_obj:
				return Response({'message': 'appointment not found'}, status=status.HTTP_404_NOT_FOUND)
			
			# Get the user's timezone (Assuming it's available as instance.seer_user.timezone)
			user_timezone = pytz.timezone(seer_user.timezone)
			# Get the fortune teller's timezone (Assuming it's available as instance.fortune_teller.timezone)
			fortune_timezone = pytz.timezone(fortune_teller.timezone)

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

			'''=================   convertion of timezone   ========================='''
			# Create datetime objects for the start and end times using the user's timezone
			start_time_user_timezone = user_timezone.localize(appointment_datetime_start)
			end_time_user_timezone = user_timezone.localize(appointment_datetime_end)
			# Convert the start and end times to the fortune teller's timezone
			start_time_fortune = start_time_user_timezone.astimezone(fortune_timezone)
			end_time_fortune = end_time_user_timezone.astimezone(fortune_timezone)
			# current_time = datetime.now()
			current_time = datetime.now(pytz.timezone (fortune_teller.timezone))
	
			'''=================   End of convertion of timezone   ========================='''
			
			if current_time >= end_time_fortune:
				return Response({'message': 'The appointment has expired.'},status=status.HTTP_400_BAD_REQUEST)
			if current_time < start_time_fortune:
				return Response({'message': 'The appointment is in the future.'},status=status.HTTP_400_BAD_REQUEST)
			
			''' =====================End of Check for create conversation==========================='''

			# # Check if conversation already exists
			# existing_conversation = client.conversations.conversations.list(
			# 	attributes={'fortune_teller_id': str(fortune_teller.id), 'seer_user_id': str(seer_user.id)}
			# ).first()


			# Check if conversation already exists
			existing_conversation = Conversation.objects.filter(fortune_teller=fortune_teller, seer_user=seer_user).first()
			if existing_conversation:
				# push notification
				appointment_obj.twilio_channel_sid = existing_conversation.twilio_channel_sid
				appointment_obj.save()
				registration_id = seer_user.fcm_token
				server_key = str(settings.FIREBASE_SERVER_KEY)
				if seer_user.device_type == 'Android':

					data_message = {		'type': 'conversation_start',
											'title' : 'CHAT STARTED FROM FORTUNE SIDE',
											'message' : 'Your Chat have started with'+ fortune_teller.first_name+' '+fortune_teller.last_name+', Please Join!',
											'image': fortune_teller.image,
											'twilio_channel_sid':existing_conversation.twilio_channel_sid,
											'appointment_id':appointment_id,
									}
					
					result = FCMNotification(api_key=server_key).notify_single_device(registration_id=registration_id,  data_message=data_message)
				if seer_user.device_type == 'Ios':
					message_title = 'CHAT STARTED FROM FORTUNE SIDE',
					message_body =  'Your Chat start with '+ fortune_teller.first_name+' '+fortune_teller.last_name+' please join.'
					data_message = {		'type': 'conversation_start',
											'title': 'CHAT STARTED FROM FORTUNE SIDE',
											'message': 'Your Chat have started with'+ fortune_teller.first_name+' '+fortune_teller.last_name+', Please Join!',
											'image': fortune_teller.image,
											'name': str(fortune_teller.first_name)+' '+str(fortune_teller.last_name),
											'twilio_channel_sid':existing_conversation.twilio_channel_sid,
											'appointment_id':appointment_id,
									}
					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)
				
					# end

					# system notification
				SeerUserNotifications.objects.create(message='Your Chat have started with'+ fortune_teller.first_name+' '+fortune_teller.last_name+', Please Join!',notification_type="conversation_start",seer_user=seer_user)
				return Response({'message': 'Conversation already exists',"twilio_channel_sid": existing_conversation.twilio_channel_sid},status=status.HTTP_200_OK)
			
			concatinate_names= str(fortune_teller.first_name) + str(seer_user.first_name) + str(seer_user.id) + str(fortune_teller.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(fortune_teller=fortune_teller,seer_user=seer_user)
			conversation_obj.twilio_channel_sid = conversation.sid
			conversation_obj.last_message = datetime.now()
			conversation_obj.save()
			appointment_obj.twilio_channel_sid = conversation.sid
			appointment_obj.save()

			# Create Video Room
			# video_room = client.video.v1.rooms.create(
			#                      status_callback='http://example.org',
			#                      type='peer-to-peer',
			#                      unique_name='SalesMeeting',
			# 	 				 max_participant_duration=900
			#                  )
			# Create participant attributes for the seer user
			seer_user_attributes= {"id":str(seer_user.id),"name":str(seer_user.first_name)+' '+str(seer_user.last_name),
				"image":str(seer_user.primary_image)
			}
			seer_json_attributes = json.dumps(seer_user_attributes)
			# Create participant for the seer user
			seer_user_participant = client.conversations \
				.v1 \
				.conversations(conversation.sid) \
				.participants \
				.create(identity=str(seer_user.id),attributes=seer_json_attributes)

			# Create participant attributes for the fortune teller
			fortune_teller_attributes= {"id":str(fortune_teller.id),"name":str(fortune_teller.first_name)+' '+str(fortune_teller.last_name),
				"image":str(fortune_teller.image)
			}
			fortune_json_attributes = json.dumps(fortune_teller_attributes)
			# Create participant for the fortune teller
			fortune_teller_participant = client.conversations \
				.v1 \
				.conversations(conversation.sid) \
				.participants \
				.create(identity=str(fortune_teller.id),attributes=fortune_json_attributes)

			conversation_obj.seer_user_twilio_id = seer_user_participant.sid
			conversation_obj.fortune_teller_twilio_id = fortune_teller_participant.sid
			conversation_obj.save()

			# push notification

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

				data_message = {		'type': 'conversation_start',
										'title' : 'CHAT STARTED FROM FORTUNE SIDE',
										'message' : 'Your Chat have started with'+ fortune_teller.first_name+' '+fortune_teller.last_name+', Please Join!',
										'image': fortune_teller.image,
										'twilio_channel_sid':conversation_obj.twilio_channel_sid,
										'appointment_id':appointment_id,	
								}
				
				result = FCMNotification(api_key=server_key).notify_single_device(registration_id=registration_id,  data_message=data_message)
			if seer_user.device_type == 'Ios':
				message_title = 'CHAT STARTED FROM FORTUNE SIDE',
				message_body = 'Your Chat have started with'+ fortune_teller.first_name+' '+fortune_teller.last_name+', Please Join!'
				data_message = {		'type': 'conversation_start',
										'title' : 'CHAT STARTED FROM FORTUNE SIDE',
										'message' : 'Your Chat have started with'+ fortune_teller.first_name+' '+fortune_teller.last_name+', Please Join!',
										'image': fortune_teller.image,
										'twilio_channel_sid':conversation_obj.twilio_channel_sid,
										'appointment_id':appointment_id,
								}
				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)
			
				# end

				# system notification
			SeerUserNotifications.objects.create(message='Your Chat have started with'+ fortune_teller.first_name+' '+fortune_teller.last_name+', Please Join!',notification_type="conversation_start",seer_user=seer_user)

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

'''================== Conversation between Seer User and Seer User =================='''


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

			seer_user_obj = SeerUser.objects.filter(id=uid).first()
			if not seer_user_obj:
				return Response({'message': 'user not found'}, status=status.HTTP_404_NOT_FOUND)
			data = request.data
			seer_user_id = data.get('seer_id')
			if not seer_user_id:
				return Response({'message': 'seer_id is  required'}, status=status.HTTP_400_BAD_REQUEST)
			# Get seer user
			seer_user = SeerUser.objects.filter(id=seer_user_id).first()
			if not seer_user:
				return Response({'message': 'Seer User not found'}, status=status.HTTP_404_NOT_FOUND)
			
			# # Check if conversation already exists between the two users using Twilio API
			# conversations = client.conversations \
			# 	.v1 \
			# 	.conversations \
			# 	.list(friendly_name=f"conversation_{seer_user_obj.id}_{seer_user_id}")
			
			# if conversations:
			# 	return Response({'message': 'Conversation already exists'},
			# 					status=status.HTTP_200_OK)


			# Check if conversation already exists between the two users
			existing_conversation = SeerUserConversation.objects.filter(
				Q(seer_user_one=seer_user_obj, seer_user_two_id=seer_user_id) |
				Q(seer_user_one_id=seer_user_id, seer_user_two=seer_user_obj)
			).first()

			if existing_conversation:
				return Response({'message': 'Conversation already exists',"twilio_channel_sid": existing_conversation.twilio_channel_sid},status=status.HTTP_200_OK)
	
			concatinate_names= str(seer_user_obj.first_name) + str(seer_user.first_name) + str(seer_user.id) + str(seer_user_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 = SeerUserConversation.objects.create(seer_user_one=seer_user_obj,seer_user_two=seer_user)
			conversation_obj.twilio_channel_sid = conversation.sid
			conversation_obj.last_message = datetime.now()
			conversation_obj.save()

			# Create Video Room
			# video_room = client.video.v1.rooms.create(
			#                      status_callback='http://example.org',
			#                      type='peer-to-peer',
			#                      unique_name='SalesMeeting',
			# 	 				 max_participant_duration=900
			#                  )
			# Create participant attributes for the seer user
			seer_user_attributes= {"id":str(seer_user.id),"name":str(seer_user.first_name)+' '+str(seer_user.last_name),
				"image":str(seer_user.primary_image)
			}
			seer_json_attributes = json.dumps(seer_user_attributes)
			# Create participant for the seer user
			seer_user_participant = client.conversations \
				.v1 \
				.conversations(conversation.sid) \
				.participants \
				.create(identity=str(seer_user.id),attributes=seer_json_attributes)

			# Create participant attributes for the fortune teller
			seer_user_obj_attributes= {"id":str(seer_user_obj.id),"name":str(seer_user_obj.first_name)+' '+str(seer_user_obj.last_name),
				"image":str(seer_user_obj.primary_image)
			}
			seer_two_json_attributes = json.dumps(seer_user_obj_attributes)
			# Create participant for the fortune teller
			seer_user_obj_participant = client.conversations \
				.v1 \
				.conversations(conversation.sid) \
				.participants \
				.create(identity=str(seer_user_obj.id),attributes=seer_two_json_attributes)

			conversation_obj.seer_user_one_twilio_id = seer_user_obj_participant.sid
			conversation_obj.seer_user_two_twilio_id = seer_user_participant.sid
			conversation_obj.save()
			return Response({"message":'success',"twilio_channel_sid": conversation_obj.twilio_channel_sid})
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


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

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

			conversations = Conversation.objects.filter(fortune_teller=fortune_teller)

			conversation_list = []
			for conversation in conversations:
				conversation_data = {
					"id": conversation.id,
					"twilio_channel_sid": conversation.twilio_channel_sid,
				}
				conversation_list.append(conversation_data)

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

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

			seer_user_obj = SeerUser.objects.filter(id=uid).first()
			if not seer_user_obj:
				return Response({'message': 'user not found'}, status=status.HTTP_404_NOT_FOUND)

			conversations = SeerUserConversation.objects.filter(Q(seer_user_one=seer_user_obj)|Q(seer_user_two=seer_user_obj))
			
			conversation_list = []
			for conversation in conversations:
				
				# Determine the other user in the conversation
				other_user = conversation.seer_user_one if conversation.seer_user_one != seer_user_obj else conversation.seer_user_two
				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,
					"name": str(other_user.first_name) + ' ' + str(other_user.last_name),
					"image": other_user.primary_image,
					"last_message":last_message,
					"time":time,
					"message_date":message_date,
				}
				conversation_list.append(conversation_data)

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

		

class DeleteConversation(APIView):
	def post(self,request):
		try:
			conversations = SeerUserConversation.objects.all()
			for cover in conversations:
				client.conversations.v1.conversations(cover.twilio_channel_sid) \
						.delete()
				cover.delete()
			return Response({"message":'success'})
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

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

			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			data = request.data
			identity = fortune_teller.id
			appointment_id = data.get('appointment_id')
			if not appointment_id:
				return Response({'message': 'appointment_id is  required'}, status=status.HTTP_400_BAD_REQUEST)
			appointment_obj = FortuneAppointmentBook.objects.filter(id=appointment_id).first()
			if not appointment_obj:
				return Response({'message': 'appointment not found'}, status=status.HTTP_404_NOT_FOUND)
			
			'''=================   check remaining time   ========================='''
			appointment_time = appointment_obj.appointment_time
			appointment_date = appointment_obj.appointment_date
			booked_start, booked_end = map(str.strip, appointment_time.split('-'))
			appointment_datetime = datetime.strptime(appointment_date + ' ' + booked_end.strip(), "%d %B %Y %I:%M %p")
			
			# Get the user's timezone (Assuming it's available as seer_user.timezone)
			user_timezone = pytz.timezone(appointment_obj.seer_user.timezone)
			# Get the fortune teller's timezone (Assuming it's available as fortune_teller.timezone)
			fortune_timezone = pytz.timezone(fortune_teller.timezone)

			'''=================   convertion of timezone   ========================='''

			# Create datetime objects for the start and end times using the user's timezone
			# start_time_user_timezone = user_timezone.localize(appointment_datetime_start)
			end_time_user_timezone = user_timezone.localize(appointment_datetime)
			
			# Convert the start and end times to the fortune teller's timezone
			# start_time_fortune = start_time_user_timezone.astimezone(fortune_timezone)
			end_time_fortune = end_time_user_timezone.astimezone(fortune_timezone)
	
			# current_time = datetime.now()
			current_datetime = datetime.now(pytz.timezone (fortune_teller.timezone))
			
			'''====================  End of  convertion of timezone  ===================='''

			# current_datetime = datetime.now()
			if current_datetime <= end_time_fortune:
				time_difference = end_time_fortune - current_datetime

			else:
				# time_difference = timedelta(days=1) - (current_datetime - end_time_fortune)
				time_difference = timedelta(days=1) - (end_time_fortune - current_datetime)
				time_difference = -time_difference
			
			'''====================  End of check remaining time ===================='''
			token = AccessToken(account_sid,api_sid,api_secret,identity=identity)
			# if sync_service_sid:
			# 	sync_grant = SyncGrant(service_sid=sync_service_sid)
			# 	token.add_grant(sync_grant)

			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,
			'remain_time':time_difference,
			'token':token.to_jwt(),
			}
			return Response({'message':'Token Created Successfully','data':alldata})
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		

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

			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			data = request.data
			identity = fortune_teller.id
			token = AccessToken(account_sid,api_sid,api_secret,identity=identity)
			# if sync_service_sid:
			# 	sync_grant = SyncGrant(service_sid=sync_service_sid)
			# 	token.add_grant(sync_grant)

			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({'message':'Token Created Successfully','data':alldata})
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


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

			seer_user_obj = SeerUser.objects.filter(id=uid).first()
			if not seer_user_obj:
				return Response({'message': 'user not found'}, status=status.HTTP_404_NOT_FOUND)
			data = request.data
			identity = seer_user_obj.id
			appointment_id = data.get('appointment_id')
			if appointment_id:
				appointment_obj = FortuneAppointmentBook.objects.filter(id=appointment_id).first()
				if not appointment_obj:
					return Response({'message': 'appointment not found'}, status=status.HTTP_404_NOT_FOUND)
				
				'''=================   check remaining time   ========================='''
				appointment_time = appointment_obj.appointment_time
				appointment_date = appointment_obj.appointment_date
				booked_start, booked_end = map(str.strip, appointment_time.split('-'))
				appointment_datetime = datetime.strptime(appointment_date + ' ' + booked_end.strip(), "%d %B %Y %I:%M %p")
				# current_datetime = datetime.now()
				user_timezone = pytz.timezone(seer_user_obj.timezone)
				appointment_datetime = user_timezone.localize(appointment_datetime)
				current_datetime = datetime.now(pytz.timezone (seer_user_obj.timezone))
				if current_datetime <= appointment_datetime:
					time_difference = appointment_datetime - current_datetime
				else:
					time_difference = timedelta(days=1) - (appointment_datetime - current_datetime)
					time_difference = -time_difference
			else:
				time_difference = None
				
				'''====================  End of check remaining time ===================='''
			token = AccessToken(account_sid,api_sid,api_secret,identity=identity)
			# if sync_service_sid:
			# 	sync_grant = SyncGrant(service_sid=sync_service_sid)
			# 	token.add_grant(sync_grant)

			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,
			'remain_time':time_difference,
			'token':token.to_jwt(),
			}
			return Response({'message':'Token Created Successfully','data':alldata})
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)



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

			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			data = request.data
			room_name = data.get('room_name')
			appointment_id = data.get('appointment_id')
			user_id = data.get('user_id')
			if not room_name:
				return Response({'message': 'room_name is  required'}, status=status.HTTP_400_BAD_REQUEST)
			if not appointment_id:
				return Response({'message': 'appointment_id is  required'}, status=status.HTTP_400_BAD_REQUEST)
			if not user_id:
				return Response({'message': 'user_id is  required'}, status=status.HTTP_400_BAD_REQUEST)
			seer_user = SeerUser.objects.filter(id=user_id).first()
			appointment_obj = FortuneAppointmentBook.objects.filter(id=appointment_id).first()
			if not seer_user:
				return Response({'message': 'Seer User not found'}, status=status.HTTP_404_NOT_FOUND)
			if not appointment_obj:
				return Response({'message': 'appointment not found'}, status=status.HTTP_404_NOT_FOUND)

			# Get the user's timezone (Assuming it's available as instance.seer_user.timezone)
			user_timezone = pytz.timezone(seer_user.timezone)
			# Get the fortune teller's timezone (Assuming it's available as instance.fortune_teller.timezone)
			fortune_timezone = pytz.timezone(fortune_teller.timezone)

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

			'''=================   convertion of timezone   ========================='''
			# Create datetime objects for the start and end times using the user's timezone
			start_time_user_timezone = user_timezone.localize(appointment_datetime_start)
			end_time_user_timezone = user_timezone.localize(appointment_datetime_end)
			# Convert the start and end times to the fortune teller's timezone
			start_time_fortune = start_time_user_timezone.astimezone(fortune_timezone)
			end_time_fortune = end_time_user_timezone.astimezone(fortune_timezone)
			# current_time = datetime.now()
			current_time = datetime.now(pytz.timezone (fortune_teller.timezone))
	
			'''=================   End of convertion of timezone   ========================='''

			if current_time >= end_time_fortune:
				return Response({'message': 'The appointment has expired.'},status=status.HTTP_400_BAD_REQUEST)
			if current_time < start_time_fortune:
				return Response({'message': 'The appointment is in the future.'},status=status.HTTP_400_BAD_REQUEST)
			
			''' ==================End of Check for create conversation====================== '''
			
			room = client.video.v1.rooms.create(status_callback='http://example.org',unique_name=room_name)
			video_room_obj = VideoRooms.objects.create(twilio_room_sid=room.sid)
			appointment_obj.twilio_room_name = room_name
			appointment_obj.save()

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

				data_message = {		'type': 'video_start',
										'title' : 'VIDEO STARTED FROM FORTUNE SIDE',
										'message' : 'Your Video Chat have started with'+ fortune_teller.first_name+' '+fortune_teller.last_name+', Please Join!',
										'image': fortune_teller.image,
										'twilio_room_sid':room.sid,
										'room_name':room_name,
										'appointment_id':appointment_id,
								}
				
				result = FCMNotification(api_key=server_key).notify_single_device(registration_id=registration_id,  data_message=data_message)
			if seer_user.device_type == 'Ios':
				message_title = 'VIDEO STARTED FROM FORTUNE SIDE',
				message_body =  'Your Video Chat start with '+ fortune_teller.first_name+' '+fortune_teller.last_name+' please join.'
				data_message = {		'type': 'video_start',
										'title': 'VIDEO STARTED FROM FORTUNE SIDE',
										'message': 'Your Video Chat have started with'+ fortune_teller.first_name+' '+fortune_teller.last_name+', Please Join!',
										'image': fortune_teller.image,
										'twilio_room_sid':room.sid,
										'room_name':room_name,
										'appointment_id':appointment_id,
								}
				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)
			
				# end

			# system notification
			SeerUserNotifications.objects.create(message='Your Video Chat have started with'+ fortune_teller.first_name+' '+fortune_teller.last_name+', Please Join!',notification_type="video_start",seer_user=seer_user)
			return Response({'message':'success','twilio_room_sid':room.sid})
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


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

			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
			if not fortune_teller:
				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
			data = request.data
			identity =  identity = str(fortune_teller.id) + ','+ str(fortune_teller.first_name)+str(fortune_teller.last_name) + ','+ str(fortune_teller.image)
			room_name = data.get('room_name')
			if not room_name:
				return Response({'message': 'room_name is  required'}, status=status.HTTP_400_BAD_REQUEST)
			appointment_id = data.get('appointment_id')
			if not appointment_id:
				return Response({'message': 'appointment_id is  required'}, status=status.HTTP_400_BAD_REQUEST)
			appointment_obj = FortuneAppointmentBook.objects.filter(id=appointment_id).first()
			if not appointment_obj:
				return Response({'message': 'appointment not found'}, status=status.HTTP_404_NOT_FOUND)
			
			'''=================   check remaining time   ========================='''
			appointment_time = appointment_obj.appointment_time
			appointment_date = appointment_obj.appointment_date
			booked_start, booked_end = map(str.strip, appointment_time.split('-'))
			appointment_datetime = datetime.strptime(appointment_date + ' ' + booked_end.strip(), "%d %B %Y %I:%M %p")
			
			# Get the user's timezone (Assuming it's available as seer_user.timezone)
			user_timezone = pytz.timezone(appointment_obj.seer_user.timezone)
			# Get the fortune teller's timezone (Assuming it's available as fortune_teller.timezone)
			fortune_timezone = pytz.timezone(fortune_teller.timezone)

			'''=================   convertion of timezone   ========================='''

			# Create datetime objects for the start and end times using the user's timezone
			# start_time_user_timezone = user_timezone.localize(appointment_datetime_start)
			end_time_user_timezone = user_timezone.localize(appointment_datetime)
			
			# Convert the start and end times to the fortune teller's timezone
			# start_time_fortune = start_time_user_timezone.astimezone(fortune_timezone)
			end_time_fortune = end_time_user_timezone.astimezone(fortune_timezone)
	
			# current_time = datetime.now()
			current_datetime = datetime.now(pytz.timezone (fortune_teller.timezone))
			
			'''====================  End of  convertion of timezone  ===================='''

			
			if current_datetime <= end_time_fortune:
				time_difference = end_time_fortune - current_datetime
			else:
				time_difference = timedelta(days=1) - (end_time_fortune - current_datetime)
				time_difference = -time_difference
			'''====================  End of check remaining time ===================='''
			token = AccessToken(account_sid,api_sid,api_secret,identity=identity)
		
			video_grant = VideoGrant(room=room_name)
			token.add_grant(video_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,
			'remain_time':time_difference,
			'token':token.to_jwt(),
			}
			return Response({'message':'Token Created Successfully','data':alldata})
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)



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

			seer_user = SeerUser.objects.filter(id=uid).first()
			if not seer_user:
				return Response({'message': 'user not found'}, status=status.HTTP_404_NOT_FOUND)
			data = request.data
			identity =  identity = str(seer_user.id) + ','+ str(seer_user.first_name)+str(seer_user.last_name) + ','+ str(seer_user.primary_image)
			room_name = data.get('room_name')
			if not room_name:
				return Response({'message': 'room_name is  required'}, status=status.HTTP_400_BAD_REQUEST)
			
			appointment_id = data.get('appointment_id')
			if not appointment_id:
				return Response({'message': 'appointment_id is  required'}, status=status.HTTP_400_BAD_REQUEST)
			appointment_obj = FortuneAppointmentBook.objects.filter(id=appointment_id).first()
			if not appointment_obj:
				return Response({'message': 'appointment not found'}, status=status.HTTP_404_NOT_FOUND)
			
			'''=================   check remaining time   ========================='''
			appointment_time = appointment_obj.appointment_time
			appointment_date = appointment_obj.appointment_date
			booked_start, booked_end = map(str.strip, appointment_time.split('-'))
			appointment_datetime = datetime.strptime(appointment_date + ' ' + booked_end.strip(), "%d %B %Y %I:%M %p")
			# current_datetime = datetime.now()
			user_timezone = pytz.timezone(seer_user.timezone)
			appointment_datetime = user_timezone.localize(appointment_datetime)
			current_datetime = datetime.now(pytz.timezone (seer_user.timezone))
			if current_datetime <= appointment_datetime:
				time_difference = appointment_datetime - current_datetime
			else:
				time_difference = timedelta(days=1) - (appointment_datetime - current_datetime)
				time_difference = -time_difference

			'''====================  End of check remaining time ===================='''

			token = AccessToken(account_sid,api_sid,api_secret,identity=identity)
		
			video_grant = VideoGrant(room=room_name)
			token.add_grant(video_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,
			'remain_time':time_difference,
			'token':token.to_jwt(),
			}
			return Response({'message':'Token Created Successfully','data':alldata})
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class FinishAppointment(APIView):
	def post(self,request):
		try:	
			data = request.data
			appointment_id = data.get('appointment_id')
			if not appointment_id:
				return Response({'message': 'id is  required'}, status=status.HTTP_400_BAD_REQUEST)
			appointment_obj = FortuneAppointmentBook.objects.filter(id=appointment_id).first()
			if not appointment_obj:
				return Response({'message': 'appointment not found'}, status=status.HTTP_404_NOT_FOUND)
			appointment_obj.appointment_status = 'Completed'
			appointment_obj.appointment_completed = True
			appointment_obj.save()
			general_obj =GeneralSettings.objects.all().first()
			if general_obj:
				commision_percent = general_obj.commission_percentage
				total_amount = appointment_obj.price * (commision_percent / 100)
				commision_amount = int(appointment_obj.price) - int(total_amount)
			else:
				commision_amount= appointment_obj.price
				total_amount = 0
			"""========== This code transfer the amount to fortune teller connected stripe account ========="""
			fortune_obj = FortuneTeller.objects.filter(id=appointment_obj.fortune_teller.id).first()
			tranfer_amount = TransferToConnectedAccount(fortune_obj.stripe_connect_account_id,commision_amount,appointment_obj.appointment_id)
			"""========== End Of Code ========="""
			
			"""========== This code transfer the amount to fortune teller wallet/Earning  ========="""
			wallet_obj = FotuneTellerWallet.objects.filter(fortune_teller=appointment_obj.fortune_teller).first()
			if wallet_obj:
				wallet_obj.amount += commision_amount
				wallet_obj.save()
			else:	
				FotuneTellerWallet.objects.create(fortune_teller=appointment_obj.fortune_teller,amount=commision_amount)
			"""========== End Of Code ========="""

			subject = 'Payment Received'
			html_message = render_to_string('payout_approved_email.html',{'email':fortune_obj.email,'first_name':fortune_obj.first_name,'last_name':fortune_obj.last_name,'received_date':datetime.now(),'amount':commision_amount,'commission':total_amount})
			plain_message = html_message
			from_email = settings.EMAIL_HOST_USER
			to = appointment_obj.fortune_teller.email
			mail.send_mail(subject, plain_message, from_email, [to], html_message=html_message)
			messages.success(request, "Status changed successfully")
			FortuneTellerNotifications.objects.create(message='You have received a payment of $'+str(commision_amount)+ 'successfully.',notification_type="appointment_earning",fortune_teller=fortune_obj)
			
			FortuneTellerTranscations.objects.create(transcation_id=generateTranscationsIdFortune(),seer_user=appointment_obj.seer_user,fortune_teller=appointment_obj.fortune_teller,amount=commision_amount,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 GetAppointment(APIView):
	def get(self,request):
		try:	
			data = request.query_params
			appointment_id = data.get('appointment_id')
			if not appointment_id:
				return Response({'message': 'id is  required'}, status=status.HTTP_400_BAD_REQUEST)
			appointment_obj = FortuneAppointmentBook.objects.filter(id=appointment_id).first()
			if not appointment_obj:
				return Response({'message': 'appointment not found'}, status=status.HTTP_404_NOT_FOUND)
			all_data = {
				'appointment_status':appointment_obj.appointment_status,
				'appointment_completed':appointment_obj.appointment_completed
			}
			return Response({'message':'success','data':all_data})
		except Exception as e:
				return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)

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

# 			fortune_teller = FortuneTeller.objects.filter(id=uid).first()
# 			if not fortune_teller:
# 				return Response({'message': 'Fortune teller not found'}, status=status.HTTP_404_NOT_FOUND)
# 			data = request.data
# 			room_name = data.get('room_name')
# 			if not room_name:
# 				return Response({'message': 'room_name is  required'}, status=status.HTTP_404_NOT_FOUND)
# 			room = room = client.video.v1.rooms('DailyStandup').fetch()
# 			return Response({'message':'success','twilio_room_sid':room.sid})
# 		except Exception as e:
# 			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)



class dummy(APIView):
	def get(self,request):
		try:
			data = {"room_name":"SimpleCheck",
			"twilio_room_sid":'RM03d12a938b7fdf21308ff7de7693ef80'}
			return Response({'message':'success','data':data})
		except Exception as e:
			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)

















































# class FetchGroup(APIView):
# 	def post(self,request):
# 		try:
# 			data = request.data
# 			twilio_channel_sid = data.get('twilio_channel_sid')
# 			conversation = client.conversations \
# 					 .v1 \
# 					 .conversations(twilio_channel_sid) \
# 					 .fetch()
# 			return Response({"message":'success',"chat_service_sid":conversation.chat_service_sid})
# 		except Exception as e:
# 			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)
		
# class AddParticipant(APIView):
# 	def post(self,request):
# 		try:
# 			data = request.data
# 			data = request.data
# 			twilio_channel_sid = data.get('twilio_channel_sid')
# 			participant = client.conversations \
# 					.v1 \
# 					.conversations(twilio_channel_sid) \
# 					.participants \
# 					.create(identity='testPineapple')
# 			return Response({"message":'success',"sid":participant.sid})
# 		except Exception as e:
# 			return Response({"message":str(e)},status=status.HTTP_500_INTERNAL_SERVER_ERROR)


# class CreateUserToUserConversation(APIView):
#     def post(self,request):
#         session_token=request.META.get('HTTP_AUTHORIZATION')
#         if not session_token:
#             return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'session_token is required'})
#         try:
#             user_obj=User.objects.get(token=session_token)
#         except Exception as e:
#             return Response({'status_code':status.HTTP_401_UNAUTHORIZED,'status_message':'Invalid session token'},status=status.HTTP_401_UNAUTHORIZED)
#         serializer = CreateGroupSerializer(data=request.data)
#         twilio_room_name = randomStringFunctionForImage()
#         if serializer.is_valid():
#             conversation = None
#             for conv in client.conversations.conversations.list():
#                 if conv.friendly_name == twilio_room_name:
#                     conversation = conv
#                     break
#             if conversation is not None:
#                 return Response({'status_code':status.HTTP_400_BAD_REQUEST,'status_message':'Room Already Exist'})
#             else:
#                 room_obj = Rooms.objects.create(room_name = request.data.get('group_name'),created_by=user_obj,count_users=request.data.get('count_users'),type=1)
			   
#                 if request.data.get('room_logo'):
#                         fileUrl=uploadTheProfile(request.data.get('room_logo'))
#                         fileUrl=str(settings.BASE_URL)+'/'+fileUrl
#                         room_obj.room_logo=str(fileUrl)
						
#                         room_obj.save()
#                 list_user = request.data.get('users')
#                 kk = json.loads(list_user)
#                 conv_id = client.conversations.conversations.create(friendly_name=twilio_room_name)
#                 client.video.v1.rooms.create(record_participants_on_connect=True,status_callback='http://example.org',type='group',unique_name=twilio_room_name)
#             room_obj.twilio_room_id = conv_id.sid
#             room_obj.last_message =  datetime.datetime.now()
#             time.sleep(1)
#             now2 = datetime.datetime.now()
#             Rooms.objects.filter(id=1).update(last_message=now2)
#             room_id = conv_id.sid

#             room_obj.save()
#             for users in kk:
#                 uid_obj = users['user_id']
#                 user_data = User.objects.filter(id=uid_obj).first()
#                 Praticipants_obj = Praticipants.objects.create(room=room_obj,user_id=user_data.id)
#                 identity = user_data.id
#                 python_obj= {"name":str(user_data.username),
#                         "avatar":str(user_data.avatar)}
#                 j_data = json.dumps(python_obj)
#                 participant = client.conversations \
#                 .v1 \
#                 .conversations(room_id) \
#                 .participants \
#                 .create(identity=identity,attributes=j_data)
#                 Praticipants_obj.user_twilio_id = participant.sid
#                 Praticipants_obj.save()
#                 ReportLogs.objects.create(user=user_data,room=room_obj,joined_date=datetime.datetime.now())
#                 user_dataid = User.objects.filter(id=users['user_id']).first() 
#                 UserNotifications.objects.create(message=user_obj.username+" added you in the "+ request.data.get('group_name'),user_id=user_dataid.id)
			
#             return Response({'status_code':status.HTTP_200_OK,'status_message':'Group created successfully'})
#         else:
#             return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)