from django.shortcuts import render
# from rest_framework import viewsets,permissions
from .models import Timeslots, Notes
# from .serializers import EmployeeSerializer,DepartmentSerializer
from django.views.decorators.csrf import csrf_exempt

from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework import status
from rest_framework.response import Response
from django.core.mail import send_mail
from django.contrib.auth.models import User
from rest_framework_simplejwt.tokens import RefreshToken
from django.http import JsonResponse
from rest_framework_simplejwt.tokens import Token
import json

import jwt

import requests
from time import time
from datetime import datetime as dt
import datetime 
from datetime import date
from datetime import timedelta

from django.conf import settings
from django.contrib.auth.hashers import make_password
from django.utils import timezone
from CommonApp.utils import CreateNotification, CreateMeetingLink, sendMail

from .forms import TemplateForm, CreateNotesForm, CancelBooking, ReportClient, UpdateNotesForm, GetNotesForm, GenerateMSMeetingLinkAgain, StarRatingFormClient
from .decorators import user_is_coach
from Client.models import Bookings, UserReports
from Employee.models import Leaves
from CommonApp.models import Messages, Ratings
from django.db.models import Q

# Create your views here.

# class EmployeeView(viewsets.ModelViewSet):
#     queryset=Employee.objects.all()
#     serializer_class=EmployeeSerializer

# class DepartmentView(viewsets.ModelViewSet):
#     queryset=Department.objects.all()
#     serializer_class=DepartmentSerializer
	#permission_classes=(permissions.IsAuthenticatedOrReadOnly,)


# @api_view(('GET',))
# # @authentication_classes([])
# # @permission_classes([])
# def hello(request):
#     # user = User.objects.filter(username='prashant').first()
#     user = User.objects.filter(username="prashant")
#     user = user.first()
#     # user = list(user)
#     # for i in user:
#     #     user = i
#     # encoded = jwt.encode({'id':user.id, 'exp':1654510342}, settings.SECRET_KEY, algorithm='HS256')
#     # refresh = RefreshToken.for_user(user)
#     # user['toen'] = encoded

#     # return Response(json.dumps(encoded), status=HTTP_200_OK)
#     # return JsonResponse({"models_to_return": user})

#     # refresh = RefreshToken.for_user(user)
#     # return refresh
#     # data = {'one':'Gazab', 'token':refresh}
#     # emailto = 'prashant@six30labs.io'
#     # res = send_mail("hello paul", "comment tu vas?", "paul@polo.com", [emailto])

#     # user.password = make_password("123")
#     # user.save()
#     return Response(status=status.HTTP_200_OK, 
#         data={
#             'message': 'Success', 
#             'data': user
#             # 'data': str(refresh.access_token)
#         }
#     )


@csrf_exempt
@api_view(('POST',))
@user_is_coach
def SaveTemplate(request):
	if request.method == 'POST':
		if request.user.userprofile.user_type != 'coach':
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ['User is not coach, So timeslots can not be updated']
					}
				}
			)
		# raise Exception(type(request.POST.getlist('days_name')))

		days_name = request.POST.getlist('days_name')
		days = ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']
		check = all(item in days for item in days_name)
		if check == False:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'days_name': ["Days are wrong"]
					}
				}
			)
		# form = TemplateForm(request.POST)
		# if form.is_valid():
		days_name = request.POST.getlist('days_name')
		for key, val in enumerate(days_name):
			# raise Exception(str(val))
			check_slot = Timeslots.objects.filter(coach_id=request.user.id, day_name=val).first()
			if check_slot:
				check_slot.slots = json.dumps((request.POST.getlist('slots').replace(" ", ""))[key])
				check_slot.created_at = timezone.now()
				check_slot.coach_id   = request.user.id
				check_slot.save()
			else:
				check_slot = Timeslots.objects.create(slots=json.dumps((request.POST.getlist('slots').replace(" ", ""))[key]), updated_at=timezone.now(), created_at = timezone.now(), coach_id = request.user.id, day_name = val, day_number=key)
				check_slot.save()
			# raise Exception(check_slot)

		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': 'Data Updated successfully!', 
				'data': ''
			}
		)
	return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED, 
		data={
			'code': 'Error', 
			'message': 'Wrong Method', 
			'data': None
		}
	)

@csrf_exempt
@api_view(('GET',))
@user_is_coach
def GetTimeslots(request):
	if 'date' not in request.GET:
		return Response(status=status.HTTP_400_BAD_REQUEST, 
			data={
				'code': 'Error', 
				'message': 'Something went wrong', 
				'data': {
					'error': ["Date field is required."]
				}
			}
		)
	date = request.GET['date']
	day_name= ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday','Sunday']
	day = dt.strptime(date, '%Y-%m-%d').weekday()

	slots = Timeslots.objects.filter(coach_id=request.user.id, day_name=day_name[day]).first()
	if slots == None:
		return Response(status=status.HTTP_206_BAD_REQUEST, 
			data={
				'code': 'Error', 
				'message': 'Slots are not available', 
				'data': None
			}
		)
	bookings = Bookings.objects.filter(session_date=date, coach_id=request.user.id).filter(~Q(status='cancelled'))
	bookings = [i.serialize for i in bookings]
	# raise Exception(bookings[0]['user_name'])
	return Response(status=status.HTTP_200_OK, 
		data={
			'code': 'Success', 
			'message': 'Data Found!', 
			'data': {'slots': slots.serialize, 'booked_slots': bookings}
		}
	)

@csrf_exempt
@api_view(('POST',))
@user_is_coach
def InsertDataNotes(request):
	# raise Exception('hii')
	form = CreateNotesForm(request.POST)
	if form.is_valid():
		client_id = request.POST['client_id']
		data = request.POST['data']
		check_booking = Bookings.objects.filter(user_id=client_id, coach_id=request.user.id).first()
		if check_booking == False:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ["There is not any previous or upcoming booking with this user"]
					}
				}
			)

		today = dt.today()
		year = today.year
		month = today.month
		day = today.day
		check_note = Notes.objects.filter(client_id=client_id, coach_id=request.user.id, created_at__year=year, created_at__month=month, created_at__day=day).first()
		# raise Exception(check_note)
		if check_note == None:
			check_note = Notes.objects.create(client_id=client_id, coach_id=request.user.id, data=data)
			check_note.save()
		else:
			Notes.objects.filter(client_id=client_id, coach_id=request.user.id, created_at__year=year, created_at__month=month, created_at__day=day, id=check_note.id).update(data=data)
		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': 'Notes Created successfully!', 
				'data': check_note.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_coach
def UpdateDataNotes(request):
	form = UpdateNotesForm(request.POST)
	if form.is_valid():
		note_id = request.POST['note_id']
		client_id = request.POST['client_id']
		data = request.POST['data']

		check_note = Notes.objects.filter(id=note_id, client_id=client_id, coach_id=request.user.id).first()
		if check_note is None or check_note.coach_id != request.user.id:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ["Note either does not belongs to you or belongs to this client"]
					}
				}
			)
		
		check_booking = Bookings.objects.filter(user_id=client_id, coach_id=request.user.id).first()
		if check_booking == False:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ["There is not any previous or upcoming booking with this user"]
					}
				}
			)

		Notes.objects.filter(id=note_id, client_id=client_id, coach_id=request.user.id).update(data=data)
		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': 'Notes Updated successfully!', 
				'data': ''
			}
		)
	return Response(status=status.HTTP_400_BAD_REQUEST, 
		data={
			'code': 'Error', 
			'message': 'Something went wrong', 
			'data': form.errors
		}
	)

@csrf_exempt
@api_view(('GET',))
@user_is_coach
def GetNotes(request, client_id):
	data = {}
	notes = Notes.objects.filter(coach_id=request.user.id, client_id=client_id, is_deleted=0).order_by('-is_pinned', '-id')
	# raise Exception(notes)
	data['notes'] = [i.serialize for i in notes]
	last_booking = Bookings.objects.filter(coach_id=request.user.id, user_id=client_id).order_by('-id').first()
	data['last_booking'] = last_booking.serialize
	return Response(status=status.HTTP_200_OK, 
		data={
			'code': 'Success', 
			'message': 'Notes Found successfully!', 
			'data': data
		}
	)

@csrf_exempt
@api_view(('GET',))
@user_is_coach
# def GetNote(request, note_id):
def GetNote(request):
	# raise Exception('note' in  request.GET and request.GET['note'] != '')
	if 'note' in  request.GET and request.GET['note'] != '':
		check_note = Notes.objects.filter(id=request.GET['note'], coach_id=request.user.id).first()
		# raise Exception('check_note', check_note)
		if check_note is None:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': ['This Note does not belongs to you']
				}
			)
		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success',
				'message': 'Note Found successfully!', 
				'data': check_note.serialize
			}
		)
	elif 'client' in request.GET and request.GET['client'] != '':
		today = datetime.today()
		year = today.year
		month = today.month
		day = today.day
		check_note = Notes.objects.filter(client_id=client_id, coach_id=request.user.id, created_at__year=year, created_at__month=month, created_at__day=day).first()
		# raise Exception('check_note', check_note)
		if check_note is None:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': ['This Note does not belongs to you']
				}
			)
		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success',
				'message': 'Note Found successfully!', 
				'data': check_note.serialize
			}
		)
	else:
		return Response(status=status.HTTP_400_BAD_REQUEST, 
			data={
				'code': 'Error', 
				'message': 'Something went wrong', 
				'data': ''
			}
		)



@csrf_exempt
@api_view(('POST',))
@user_is_coach
def CancelBookedSlots(request):
	form = CancelBooking(request.POST)
	if form.is_valid():
		booking_id = request.POST['booking_id']
		reason = request.POST['reason']
		check_booking = Bookings.objects.filter(id=booking_id, coach_id=request.user.id).first()
		if check_booking == None:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ["This booking does not belongs to you"]
					}
				}
			)

		Bookings.objects.filter(id=booking_id, coach_id=request.user.id).update(status='cancelled', cancelled_by_id=request.user.id, cancelled_at=timezone.now(), reason=reason)

		# saving into leave table
		leave = Leaves.objects.create(leave_from_date=check_booking.session_date, leave_type='taken_by_coach', leave_status='approved', user_id=request.user.id, slots_leave_from=check_booking.session_time)
		leave.save()

		# for saving notification and creating chat

		# creating notification
		# noti_text = 'Booking has been cancelled due to an emergency by '+request.user.userprofile.name+' on '+check_booking.session_date+' '+check_booking.session_time
		# CreateNotification('booking_cancel', check_booking.id, request.user.id, check_booking.user_id, 'n', noti_text, check_booking.coach.userprofile.category_id)

		noti_text = 'We regret to inform you that your ('+check_booking.category.name+') session with ('+check_booking.coach.userprofile.name+') on '+check_booking.session_date+' '+check_booking.session_time+' had to be canceled'	#client
		CreateNotification('booking_cancel', check_booking.id, request.user.id, check_booking.user_id, 'n', noti_text, check_booking.category_id)

		# Welcome message when session is booked
		meesg = 'Booking has been cancelled due to an emergency, Please reschedule session.'
		msg = Messages.objects.create(message=meesg, message_type='st', booking_id=booking_id, from_user_id=request.user.id, to_user_id=check_booking.user_id)
		msg.save()

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

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

		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': 'Data Update 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_coach
def ReportUser(request):
	form = ReportClient(request.POST)
	if form.is_valid():
		# raise Exception(request.user.userprofile.category_id)
		client_id = request.POST['client_id']
		report = UserReports.objects.filter(reported_by_id=request.user.id, reported_to_id=client_id).first()
		if report is not None:
			UserReports.objects.filter(reported_by_id=request.user.id, reported_to_id=client_id).delete()
			return Response(status=status.HTTP_200_OK, 
				data={
					'code': 'Success', 
					'message': 'User has been unflagged successfully!', 
					'data': ''
				}
			)
		else:
			reason = request.POST['reason']
			reprt = UserReports.objects.create(reported_by_id=request.user.id, reported_to_id=client_id, reason=reason)
			reprt.save()

			# creating notification
			noti_text = 'Your report has been successfully submitted. Our team will get back at the earliest.'	#coach
			notification = CreateNotification('client_report', reprt.id, client_id, request.user.id, 'n', noti_text, request.user.userprofile.category_id)

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

# @csrf_exempt
@api_view(('GET',))
@user_is_coach
def MakeNotePinnedUnpinned(request, note_id, is_pinned, client_id):
	if is_pinned:
		count_note = Notes.objects.filter(coach_id=request.user.id, client_id=client_id, is_pinned='1').count()
		if count_note >= 3:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ["More than 3 notes can not be pinned."]
					}
				}
			)
	check_note = Notes.objects.filter(id=note_id, coach_id=request.user.id, client_id=client_id).first()
	if check_note == None:
		return Response(status=status.HTTP_400_BAD_REQUEST, 
			data={
				'code': 'Error', 
				'message': 'Something went wrong', 
				'data': {
					'error': ["Note does not exist."]
				}
			}
		)
	if is_pinned == 0 or is_pinned == 1:
		note = Notes.objects.filter(id=note_id, coach_id=request.user.id, client_id=client_id).update(is_pinned=is_pinned)
		if is_pinned == 0:
			msg = 'Note unpinned successfully.'
		else:
			msg = 'Note pinned successfully.'
		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success', 
				'message': msg, 
				'data': ''
			}
		)
	else:
		return Response(status=status.HTTP_400_BAD_REQUEST, 
			data={
				'code': 'Error', 
				'message': 'Something went wrong', 
				'data': {
					'error': ["Wrong data is being inserted."]
				}
			}
		)

# @csrf_exempt
@api_view(('GET',))
@user_is_coach
def GetDashboardDetail(request):
	today_date = date.today()
	yesterday_date = today_date - timedelta(days = 1)
	tomorrow_date = today_date + timedelta(days = 1)
	datas = {}

	datas_today = Bookings.objects.filter(coach_id=request.user.id, session_date=today_date).filter(~Q(status='cancelled')).order_by("session_time")
	datas['datas_today'] = [i.serialize for i in datas_today]

	datas_yesterday = Bookings.objects.filter(coach_id=request.user.id, session_date=yesterday_date).filter(~Q(status='cancelled')).order_by("session_time")
	datas['datas_yesterday'] = [i.serialize for i in datas_yesterday]

	datas_tomorrow = Bookings.objects.filter(coach_id=request.user.id, session_date=tomorrow_date, status='pending').order_by("session_time")
	datas['datas_tomorrow'] = [i.serialize for i in datas_tomorrow]

	recent_notes = Notes.objects.filter(coach_id=request.user.id, is_deleted=0).order_by('-updated_at')
	datas['recent_notes'] = [i.serialize for i in recent_notes]
	# raise Exception(datas_today, datas_yesterday, datas_tomorrow)
	return Response(status=status.HTTP_200_OK, 
		data={
			'code': 'Success',
			'message': 'Data Found successfully',
			'data': datas
		}
	)

@api_view(('GET',))
@user_is_coach
def DeleteNote(request, note_id):
	check_note = Notes.objects.filter(id=note_id, coach_id=request.user.id).first()
	if check_note == None:
		return Response(status=status.HTTP_400_BAD_REQUEST, 
			data={
				'code': 'Error', 
				'message': 'Something went wrong', 
				'data': {
					'error': ["Note does not exist or  belongs to you."]
				}
			}
		)

	check_note.soft_delete()

	return Response(status=status.HTTP_200_OK, 
		data={
			'code': 'Success',
			'message': 'Note Deleted successfully',
			'data': ''
		}
	)

@api_view(('POST',))
@user_is_coach
def GenerateMSMeetingLink(request):
	form = GenerateMSMeetingLinkAgain(request.POST)
	if form.is_valid():
		booking_id = request.POST['booking_id']
		client_id = request.POST['client_id']

		check_booking = Bookings.objects.filter(id=booking_id, user_id=client_id, coach_id=request.user.id).first()
		if check_booking == None:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ["Booking does not exist or doe not belongs to you."]
					}
				}
			)
		try:
			meeting_link = CreateMeetingLink(check_booking.session_date, check_booking.session_time, request.user.userprofile)
		except:
			meeting_link = None
		check_booking.zoom_link = meeting_link
		check_booking.save()
		if meeting_link == None:
			return Response(status=status.HTTP_400_BAD_REQUEST, 
				data={
					'code': 'Error', 
					'message': 'Something went wrong', 
					'data': {
						'error': ["Something is wrong while generating meeting link, Please check MS user id is generated for the coach or not."]
					}
				}
			)
		return Response(status=status.HTTP_200_OK, 
			data={
				'code': 'Success',
				'message': 'Meeting Link created successfully',
				'data': meeting_link
			}
		)

@csrf_exempt
@api_view(('POST',))
@user_is_coach
def StarRatingClientAndSession(request):
	form = StarRatingFormClient(request.POST)
	if form.is_valid():
		
		client_id = request.POST['client_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=request.user.id, user_id=client_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=client_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=client_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=client_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
		}
	)