from django.shortcuts import render
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from django.contrib.auth.models import User

from .utils import checkSlotIsAvailable
from CommonApp.models import Category, UserProfile, Language, Ratings, Messages, Company
from .forms import SlotForm, BookForm, CancelBookingForm, StarRatingForm, ReportCoach
from Employee.models import Timeslots, Leaves
from .models import Bookings, UserReports
import datetime 
from CommonApp.utils import CreateNotification, CreateZoomLink, CreateMeetingLink, sendMail
from django.db.models import Q

from Employee.decorators import user_is_client
# from .utils import sendMail, createOtp, verificationOfOtp, createUser
# from django.http import JsonResponse
# import json
# from django.core import serializers
# from django.db import connection
# Create your views here.
@csrf_exempt
@api_view(('GET',))
@user_is_client
def categories(request):
	if request.method == 'GET':
		categories = Category.objects.all().order_by('category_order').values()
		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': 'Data found successfully!', 
				'data': categories
			}
		)
	return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED, 
		data={
			'code': 'Error', 
			'message': 'Wrong Method', 
			'data': None
		}
	)

@csrf_exempt
@api_view(('GET',))
@user_is_client
def languages(request):
	if request.method == 'GET':
		languages = Language.objects.all().values()
		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': 'Data found successfully!', 
				'data': languages
			}
		)
	return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED, 
		data={
			'code': 'Error', 
			'message': 'Wrong Method', 
			'data': None
		}
	)

@csrf_exempt
@api_view(('POST',))
@user_is_client
def coaches(request):
	if request.method == 'POST':
		if 'category' not in request.POST:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ['Invalid category']
					}
				}
			)
		# raise Exception({request.POST['language']})
		# coaches = UserProfile.objects.filter(user_type='coach')
		conditions = ' '
		condition_lgbtq = ' 1 '
		val_lgbtq = ' 1 '
		if request.POST['gender']:
			condition_gender = ''' `CommonApp_userprofile`.`gender` = %s '''
			# va_gender = request.POST['gender']
		else:
			condition_gender = ''' `CommonApp_userprofile`.`gender` != %s '''

		if request.POST['lgbtq']:
			condition_lgbtq = '''  AND `CommonApp_userprofile`.`lgbtq` = %s '''
			# val_lgbtq = request.POST['lgbtq']
		else:
			condition_lgbtq = '''  AND `CommonApp_userprofile`.`lgbtq` != %s '''
			# val_lgbtq = request.POST['lgbtq']
		if request.POST['language']:
			conditions = ''' AND `CommonApp_language_user`.`language_id` IN ('''+(",".join(request.POST.getlist('language')))+''') '''
			conditions = ''' AND (SELECT GROUP_CONCAT(`CommonApp_language_user`.`language_id`) FROM `CommonApp_language_user` WHERE `CommonApp_language_user`.`user_id`=`CommonApp_userprofile`.`user_id`'''+ conditions +''' ) IS NOT NULL'''
		# raise Exception(conditions)
		coaches = UserProfile.objects.raw('''SELECT `CommonApp_userprofile`.`id`, `CommonApp_userprofile`.`user_id`, `CommonApp_userprofile`.`name`, `CommonApp_userprofile`.`gender`, `CommonApp_userprofile`.`profile_pic`, `CommonApp_userprofile`.`dob`, `CommonApp_userprofile`.`lgbtq`, `CommonApp_userprofile`.`user_type`, `CommonApp_userprofile`.`category_id`, `CommonApp_userprofile`.`coach_time_slot`, `CommonApp_userprofile`.`specializations` FROM `CommonApp_userprofile` INNER JOIN `auth_user` ON `auth_user`.`id` = `CommonApp_userprofile`.`user_id` WHERE `auth_user`.`is_active` = 1 AND `CommonApp_userprofile`.`user_type` = 'coach' AND `CommonApp_userprofile`.`category_id` = %s AND  '''+condition_gender+condition_lgbtq+conditions, [request.POST['category'], request.POST['gender'], request.POST['lgbtq'] ])
		# raise Exception(coaches)
		data = [i.serialize for i in coaches]
		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': 'Data found successfully!', 
				'data': data
			}
		)
	return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED, 
		data={
			'code': 'Error', 
			'message': 'Wrong Method', 
			'data': None
		}
	)

@csrf_exempt
@api_view(('POST',))
@user_is_client
def getSlots(request):
	form = SlotForm(request.POST)
	if form.is_valid():
		check_coach = UserProfile.objects.filter(user_id=request.POST['coach_id'], category_id=request.POST['category_id']).count()
		if check_coach == 0:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ['Invalid coach or category']
					}
				}
			)
		check_slots = Timeslots.objects.filter(coach_id=request.POST['coach_id']).count()
		if check_slots == 0:
                    return Response(status=status.HTTP_400_BAD_REQUEST,
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'error_key':'all_slots',
					'data': {
						'error': ['Slots not available']
					}
				}
			)
		# raise Exception({request.user.date_joined})
		date=request.POST['date']
		day_name= ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday','Sunday']
		day = datetime.datetime.strptime(date, '%Y-%m-%d').weekday()
		
		slots = Timeslots.objects.filter(coach_id=request.POST['coach_id'], day_name=day_name[day], day_number=day).first()
		if slots == None:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'error_key':'this_slots',
					'data': {
						'error': ['Slots not available']
					}
				}
			)
		slots = slots.serialize

		''' getting all booking in this date '''
		bookings = Bookings.objects.filter(session_date=date, status='pending', coach_id=request.POST['coach_id'], timeslot_id=slots['id']).values_list('session_time', flat=True)
		# raise Exception(bookings)
		if len(bookings) == 0:
			bookings = []
		else:
			bookings = bookings

		''' getting all leaves in this date '''
		leaves = Leaves.objects.filter(user_id=request.POST['coach_id']).filter(Q(leave_from_date__lte=date) & Q(leave_to_date__gte=date) | Q(leave_from_date=date) & Q(leave_to_date__isnull=True))
		levaes_list = []
		if leaves != None:
			for leave in leaves:
				if leave.leave_to_date == None:	#checking one day leave
					levaes_list.extend((leave.slots_leave_from).split(','))
					# raise Exception(levaes_list)
				else:								#checking date in between dates
					if leave.leave_from_date == date:
						levaes_list.extend((leave.slots_leave_from).split(','))
					elif leave.leave_to_date == date:
						levaes_list.extend((leave.slots_leave_to).split(','))
					else:
						levaes_list.extend(slots['slots'])		
		# raise Exception(levaes_list)
		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': 'Slots found successfully!', 
				'data': {
					'slots': slots,
					'booking': bookings,
					'leaves': levaes_list
				}
			}
		)
	return Response(status=status.HTTP_400_BAD_REQUEST, 
		data={
			'code': 'Error', 
			'message': 'Something went wrong', 
			'data': form.errors
		}
	)

@csrf_exempt
@api_view(('POST',))
@user_is_client
def bookSlots(request):
	form = BookForm(request.POST)
	if form.is_valid():
		category_id = request.POST['category_id']
		date = request.POST['date']
		slot = request.POST['time_slot']
		coach_id = request.POST['coach_id']
		# raise Exception(datetime.datetime.strftime(date+' '+slot, "%Y-%m-%d %H:%I"))
		check_coach = UserProfile.objects.filter(user_id=coach_id, user_type='coach', category_id=category_id).first()

		if check_coach == None:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ['Coach does not belongs to this category']
					}
				}
			)
		# for checking the today's date and time
		if datetime.datetime.now() == datetime.datetime.strptime(date, '%Y-%m-%d'):
			# if (datetime.datetime.now()).strftime("%H:%I") > datetime.datetime.strptime(slot, "%H:%I")
			pass
		check_slot_is_available = checkSlotIsAvailable(category_id, date, slot, coach_id, request.user.id)
		if check_slot_is_available['return'] == False:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': [check_slot_is_available['message']]
					}
				}
			)

		# for checking booking is already made on upcoming date for the category
		all_coach_ids = UserProfile.objects.filter(category_id=category_id).values_list('user_id', flat=True)
		check_booking = Bookings.objects.filter(session_date__gte=datetime.datetime.now().date(), status='pending', user_id=request.user.id, coach_id__in=all_coach_ids).values_list('id', 'coach_id')
		# raise Exception(check_booking.count(), check_booking)
		if check_booking.count() > 0:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Booking already done',
					'constant_key': 'booking_already_done',
					'data_key': check_booking,
					'data': {
						'error': ['A booking is done already for this category, Please cancel that booking and then book again']
					}
				}
			)

		# check if the request has come to resolve previous relations are paused
		if 'pause_relation' in request.POST and request.POST['pause_relation'] == 'yes':
			Bookings.objects.filter(user_id=request.user.id, is_relation_paused='no', coach_id__in=all_coach_ids).update(is_relation_paused='yes')

		# checking if relationship is paused or not
		check_booking = Bookings.objects.filter(user_id=request.user.id, is_relation_paused='no', coach_id__in=all_coach_ids).filter(~Q(coach_id=coach_id)).order_by('-id').first()
		# raise Exception(check_booking.serialize['coach_name'], check_booking)
		if check_booking:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong',
					'constant_key': 'realtion_is_still_open',
					'data': {
						'error': ['A relationship is already going on with "'+check_booking.serialize['coach_name']+'", Please pause the current relationship before starting a new one.']
					}
				}
			)

		# check feedback
		check_feedback = Bookings.objects.filter(user_id=request.user.id, coach_id__in=all_coach_ids, booking__isnull=True, status='completed').values_list('id', 'coach_id')
		# raise Exception(check_feedback)
		if len(check_feedback) > 0:
			error_msgs = {}
			for key, check_feedbck in enumerate(check_feedback):
				# check_feedbck[0][2] = 123
				user_prof = User.objects.filter(id=check_feedbck[1]).first()
				error_msgs[key] = 'Please provide a rating for the previous session handled by '+user_prof.first_name+' '+user_prof.last_name
			# raise Exception(error_msgs)
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong',
					'data_key': check_feedback,		#use this ids to update rating
					'error_msgs': error_msgs,
					'data': {
						'error': ['Please give previous session a rating.']
					}
				}
			)
		# start booking here
		# zoom_link = CreateZoomLink(date, slot)
		zoom_link = CreateMeetingLink(date, slot, check_coach)  #creating meeting
		# raise Exception(zoom_link, 'Hii')
		cmpny = Company.objects.filter(domain=request.user.email.split('@')[1]).first()

		day_name= ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday','Sunday']
		day = datetime.datetime.strptime(date, '%Y-%m-%d').weekday()
		timeslot = Timeslots.objects.filter(coach_id=coach_id, day_name=day_name[day]).first()

		booking = Bookings.objects.create(session_date=date, session_time=slot, status='pending', coach_id=coach_id, timeslot_id=timeslot.id, user_id=request.user.id, zoom_link=zoom_link, category_id=category_id, company_id=cmpny.id)
		booking.save()


		# Welcome message when session is booked
		meesg = 'Hey there '+request.user.userprofile.name+'! Looking forward to our session together'
		msg = Messages.objects.create(message=meesg, message_type='st', booking_id=booking.id, from_user_id=request.user.id, to_user_id=coach_id)
		msg.save()

		# creating notification
		noti_text = 'Your ('+booking.category.name+') session has been confirmed'	#client
		CreateNotification('booking', booking.id, coach_id, request.user.id, 'n', noti_text, category_id)
		#coach
		noti_text = 'Your session with ('+request.user.userprofile.name+') has been confirmed for '+booking.session_date+' '+booking.session_time
		notification = CreateNotification('booking', booking.id, coach_id, request.user.id, 'n', noti_text, category_id)

		try:
			# sending mail to client
			subject = 'Hapsmiths Booking'
			content = booking
			template = "emails/booking-confirm.html"
			sendMail(subject, content, [request.user.email], template)

			# mail to coach
			template = "emails/booking-confirm-coach.html"
			sendMail(subject, content, [booking.coach.email], template)
		except:
			pass

		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': 'Booking has been confirmed successfully!', 
				'data': booking.id
			}
		)

	return Response(status=status.HTTP_400_BAD_REQUEST, 
		data={
			'code': 'Error', 
			'message': 'Something went wrong', 
			'data': form.errors
		}
	)

@csrf_exempt
@api_view(('POST',))
@user_is_client
def cancelBookedSlots(request):
	form = CancelBookingForm(request.POST)
	if form.is_valid():
		booking_id = request.POST['booking_id']
		category_id = request.POST['category_id']
		coach_id = request.POST['coach_id']
		if 'reason' in request.POST and request.POST['reason'] != '':
			reason = request.POST['reason']
		else:
			reason = None

		check_coach = UserProfile.objects.filter(user_id=coach_id, user_type='coach', category_id=category_id).count()
		# raise Exception(check_coach)
		if check_coach == 0:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ['Coach does not belongs to this category']
					}
				}
			)

		check_booking = Bookings.objects.filter(id=booking_id, coach_id=coach_id, user_id=request.user.id, status='pending', session_date__gte=datetime.datetime.now().date()).first()
		# raise Exception(check_booking)
		if check_booking==None:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ['Either booking does not exists or does not belongs to you']
					}
				}
			)

		check_booking.status = 'cancelled'
		check_booking.cancelled_by_id = request.user.id
		check_booking.cancelled_at = datetime.datetime.now()
		check_booking.reason = reason
		check_booking.save()

		# creating notification
		noti_text = 'We regret to inform you that your session with ('+check_booking.user.userprofile.name+') on '+check_booking.session_date+' '+check_booking.session_time+' has been canceled'	#coach
		notification = CreateNotification('booking_cancel', check_booking.id, request.user.id, coach_id, 'n', noti_text, check_booking.coach.userprofile.category_id)

		noti_text = 'Your ('+check_booking.category.name+') session has been canceled'		#client
		notification = CreateNotification('booking_cancel', check_booking.id, coach_id, request.user.id, 'n', noti_text, check_booking.coach.userprofile.category_id)

		try:
			# sending mail to client
			subject = 'Hapsmiths Booking Cancellation'
			content = check_booking
			template = "emails/booking-cancellation-client.html"
			sendMail(subject, content, [request.user.email], template)

			# mail to coach
			template = "emails/booking-cancellation-coach.html"
			sendMail(subject, content, [check_booking.coach.email], template)
		except:
			pass

		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': 'Booking has been cancelled successfully!', 
				'data': ''
			}
		)

	return Response(status=status.HTTP_400_BAD_REQUEST, 
		data={
			'code': 'Error', 
			'message': 'Something went wrong', 
			'data': form.errors
		}
	)

@csrf_exempt
@api_view(('POST',))
@user_is_client
def StarRatingCoachAndSession(request):
	form = StarRatingForm(request.POST)
	if form.is_valid():
		# pass
		coach_id = request.POST['coach_id']
		booking_id = request.POST['booking_id']
		rating = request.POST['rating']
		rating_exp_livup = request.POST['rating_exp_livup']
		rating_type = request.POST['rating_type']
		feedback = request.POST['feedback']

		check_booking = Bookings.objects.filter(id=booking_id, coach_id=coach_id, user_id=request.user.id, created_at__lt=datetime.datetime.now()).count()
		if check_booking == 0:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ['Invalid booking']
					}
				}
			)

		check_rating = Ratings.objects.filter(given_by_id=request.user.id, booking_id=booking_id, given_to_id=coach_id, rating_type=rating_type).count()
		# raise Exception(check_rating)
		if check_rating != 0:
			rating = Ratings.objects.filter(given_by_id=request.user.id, booking_id=booking_id, given_to_id=coach_id, rating_type=rating_type).update(rating=rating, feedback=feedback, rating_exp_livup=rating_exp_livup)
		else:
			rat = Ratings.objects.create(given_by_id=request.user.id, booking_id=booking_id, given_to_id=coach_id, rating=rating, rating_type=rating_type, feedback=feedback, rating_exp_livup=rating_exp_livup)
			rat.save()

		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': 'Thanks for the feedback/rating!', 
				'data': ''
			}
		)

	return Response(status=status.HTTP_400_BAD_REQUEST, 
		data={
			'code': 'Error', 
			'message': 'Something went wrong', 
			'data': form.errors
		}
	)

@csrf_exempt
@api_view(('POST',))
@user_is_client
def ReportCoaches(request):
	form = ReportCoach(request.POST)
	if form.is_valid():
		coach_id = request.POST['coach_id']
		reason = request.POST['reason']
 
		# check coach whetehr any booking has been made or not previously
		check_bookings = Bookings.objects.filter(coach_id=coach_id, user_id=request.user.id).count()
		if check_bookings == 0:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ['Invalid booking']
					}
				}
			)

		reprt = UserReports.objects.create(reported_by_id=request.user.id, reported_to_id=coach_id, reason=reason)
		reprt.save()

		# client notification
		coach = UserProfile.objects.filter(user_id=coach_id).first()
		noti_text = 'Your report has been successfully submitted. Our team will get back at the earliest.'
		CreateNotification('coach_report', reprt.id, coach_id, request.user.id, 'n', noti_text, coach.category_id)

		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': 'Reported successfully!', 
				'data': ''
			}
		)
	return Response(status=status.HTTP_400_BAD_REQUEST, 
		data={
			'code': 'Error', 
			'message': 'Something went wrong', 
			'data': form.errors
		}
	)

