from flask import Flask, jsonify, render_template, url_for, request, redirect, json
from datetime import datetime, timedelta

import pymysql, os, math, requests, uuid

from routes import app
from database.bookings import Booking
from database.booking_activity_log import BookingActivity
from database.booking_guests import BookingGuest
from database.booking_types import BookingType
from database.booking_status import BookingStatus
from database.partner import Partner
from routes import db
from routes.bookings_urls import get_booking_status_id
from functions.booking_snippets import *
from variables import *


@app.route("/bookings/no_show", methods=["POST"])
def getNoShows():
    return jsonify({"message": "Ok"}), 200


def changeToNoShows():
    yesterday_datetime = datetime.today() - timedelta(days=1)
    yesterday = yesterday_datetime.strftime("%Y-%m-%d")
    get_bookings = db.session.query(Booking)\
        .filter(Booking.deletion_marker == None)\
        .filter(Booking.actual_booking_check_in_date == None)\
        .filter(Booking.checked_in == None)\
        .filter(Booking.status == get_booking_status_id("Unconfirmed"))\
        .filter(Booking.booking_check_in_date == yesterday)\
        .all()

    yesterday = (datetime.now() - timedelta(days=1)).strftime("%Y-%m-%d")
    try:
        session_id = request.json["session_id"]
    except Exception:
        session_id = None
    if not get_bookings:
        message = []
        message.append("There are no bookings to mark as no-shows.")
        return jsonify({"message": message}), 412

    else:
        for single in get_bookings:
            if single.booking_check_in_date.strftime("%Y-%m-%d") == yesterday:
                single.status = get_booking_status_id("No-Show")
                single.updated_at = datetime.now()

                booking_activity = BookingActivity(
                    booking_activity_public_id=str(uuid.uuid4()),
                    booking_id=single.booking_public_id,
                    booking_activity_description=
                    "Booking status was updated to No Show",
                    session_id=session_id,
                    created_at=datetime.now())

                db.session.add(booking_activity)

            else:
                pass

        try:
            db.session.commit()
            db.session.close()

        except Exception:
            db.session.rollback()
            db.session.close()

            return jsonify({
                "message":
                "There was an error marking the booking as a no-show."
            }), 200

        return jsonify({"message": "Ok"}), 200


def endOfDayEvening():
	now = datetime.now()
	today = now.strftime("%Y-%m-%d")
	a_week_ago_datetime = datetime.today() - timedelta(days=7)
    #a_week_ago = a_week_ago_datetime.strftime("%Y-%m-%d")
	a_week_ago = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d")
	two_days_ago = (datetime.now() - timedelta(days=2)).strftime("%Y-%m-%d")
	get_checkIn_bookings = db.session.query(Booking)\
		.filter(Booking.deletion_marker == None)\
		.filter(Booking.actual_booking_check_in_date == None)\
		.filter(Booking.checked_in == None)\
		.filter(Booking.booking_check_in_date == today)\
		.order_by(Booking.booking_id.desc())\
		.all()
	get_checkOut_bookings = db.session.query(Booking)\
		.filter(Booking.deletion_marker == None)\
		.filter(Booking.actual_booking_check_out_date == None)\
		.filter(Booking.checked_out == None)\
		.filter(Booking.booking_check_out_date == today)\
		.order_by(Booking.booking_id.desc())\
		.all()
	get_overstayed_bookings = db.session.query(Booking)\
		.join(Transaction, Booking.booking_public_id == Transaction.booking_id)\
	 	.join(BookingType, Booking.booking_type == BookingType.booking_type_public_id)\
	 	.join(BookingStatus, Booking.status == BookingStatus.booking_status_public_id)\
		.add_columns(Booking.booking_public_id, Booking.booking_type, Booking.booking_check_in_date,\
	  	 Booking.booking_check_out_date, Booking.actual_booking_check_in_date, Booking.actual_booking_check_out_date,\
	  	 Booking.booking_done_by, Booking.checked_in, Booking.checked_out, Booking.session_id,\
	  	 Booking.created_at, Booking.updated_at, Booking.status, Booking.payment_status, Booking.booking_ref_code,\
	   	 Booking.currency,\
	 	 BookingType.booking_type_name,\
	  	 BookingStatus.booking_status_name)\
		.filter(Booking.deletion_marker == None)\
		.filter(Booking.actual_booking_check_out_date == None)\
		.filter(Booking.checked_out == None)\
		.filter(Booking.checked_in != None)\
		.filter(Booking.booking_check_out_date > a_week_ago)\
		.filter(Booking.booking_check_out_date < today)\
		.order_by(Booking.booking_id.desc())\
		.all()
	get_not_checked_in = db.session.query(Booking)\
		.join(Transaction, Booking.booking_public_id == Transaction.booking_id)\
	 	.join(BookingType, Booking.booking_type == BookingType.booking_type_public_id)\
	 	.join(BookingStatus, Booking.status == BookingStatus.booking_status_public_id)\
		.add_columns(Booking.booking_public_id, Booking.booking_type, Booking.booking_check_in_date,\
	  	 Booking.booking_check_out_date, Booking.actual_booking_check_in_date, Booking.actual_booking_check_out_date,\
	  	 Booking.booking_done_by, Booking.checked_in, Booking.checked_out, Booking.session_id,\
	  	 Booking.created_at, Booking.updated_at, Booking.status, Booking.payment_status, Booking.booking_ref_code,\
	   	 Booking.currency,\
	 	 BookingType.booking_type_name,\
	  	 BookingStatus.booking_status_name)\
		.filter(Booking.deletion_marker == None)\
		.filter(Booking.actual_booking_check_in_date == None)\
		.filter(Transaction.deletion_marker == None)\
		.filter(Booking.booking_check_in_date < today)\
		.filter(Booking.booking_check_in_date > a_week_ago)\
		.filter(Booking.actual_booking_check_in_date == None)\
		.order_by(Booking.booking_id.desc())\
		.all()
	get_no_cui = db.session.query(Booking)\
		.join(BookingType, Booking.booking_type == BookingType.booking_type_public_id)\
	 	.join(BookingStatus, Booking.status == BookingStatus.booking_status_public_id)\
		.add_columns(Booking.booking_public_id, Booking.booking_type, Booking.booking_check_in_date,\
	  	 Booking.booking_check_out_date, Booking.actual_booking_check_in_date, Booking.actual_booking_check_out_date,\
	  	 Booking.booking_done_by, Booking.checked_in, Booking.checked_out, Booking.session_id,\
	  	 Booking.created_at, Booking.updated_at, Booking.status, Booking.payment_status, Booking.booking_ref_code,\
	   	 Booking.currency,\
	 	 BookingType.booking_type_name,\
	  	 BookingStatus.booking_status_name)\
		.filter(Booking.deletion_marker == None)\
		.filter(Booking.cuinvoicenumber == None)\
		.filter(Booking.booking_check_in_date <= today)\
		.filter(Booking.booking_check_in_date > a_week_ago)\
		.filter(BookingStatus.booking_status_name != "Abandoned")\
		.filter(Booking.payment_status != 3 or Booking.payment_status == None)\
		.order_by(Booking.booking_id.desc())\
		.all()
	
	
	get_payment_status_bookings = db.session.query(Booking)\
	 .join(BookingGuest, Booking.booking_public_id == BookingGuest.booking_id)\
	 .join(BookingType, Booking.booking_type == BookingType.booking_type_public_id)\
	 .join(BookingStatus, Booking.status == BookingStatus.booking_status_public_id)\
	 .add_columns(Booking.booking_public_id, Booking.booking_type, Booking.booking_check_in_date,\
	  Booking.booking_check_out_date, Booking.actual_booking_check_in_date, Booking.actual_booking_check_out_date,\
	  Booking.booking_done_by, Booking.checked_in, Booking.checked_out, Booking.session_id,\
	  Booking.created_at, Booking.updated_at, Booking.status, Booking.payment_status, Booking.booking_ref_code,\
	  Booking.currency,\
	  BookingType.booking_type_name,\
	  BookingStatus.booking_status_name)\
	 .filter(Booking.deletion_marker == None)\
	 .filter(Booking.booking_check_in_date == today)\
	 .order_by(Booking.booking_id.desc())\
	 .all()
	
	checkin_today = []
	checkout_today =[]
	payment_status_today = []
	overstays = []
	not_checked_in = []
	no_cui = []
	
	for single_check_in in get_checkIn_bookings:
		return_data_checkin = {}
		return_data_checkin["booking_public_id"] = single_check_in.booking_public_id
		return_data_checkin["booking_ref_code"] = single_check_in.booking_ref_code
		return_data_checkin["booking_url"] ="https://bookings.olpejetaconservancy.org/booking/"+single_check_in.booking_public_id
		checkin_today.append(return_data_checkin)

	for single_check_out in get_checkOut_bookings:
		return_data_checkout = {}
		return_data_checkout["booking_public_id"] = single_check_out.booking_public_id
		return_data_checkout["booking_ref_code"] = single_check_out.booking_ref_code
		return_data_checkout["booking_url"] ="https://bookings.olpejetaconservancy.org/booking/"+single_check_out.booking_public_id
		checkout_today.append(return_data_checkout)


	for single_overstay in get_overstayed_bookings:
		return_data_overstays = {}
		return_data_overstays["booking_public_id"] = single_overstay.booking_public_id
		return_data_overstays["booking_ref_code"] = single_overstay.booking_ref_code
		return_data_overstays["booking_check_in_date"] = single_overstay.actual_booking_check_in_date
		return_data_overstays["booking_check_out_date"] = single_overstay.actual_booking_check_out_date
		return_data_overstays["booking_type_name"] = single_overstay.booking_type_name
		return_data_overstays["status"] = single_overstay.booking_status_name
		return_data_overstays["booking_url"] ="https://bookings.olpejetaconservancy.org/booking/"+single_overstay.booking_public_id
		overstays.append(return_data_overstays)


	for single_not_checked_in in get_not_checked_in:
		return_data_not_checked_in = {}
		return_data_not_checked_in["booking_public_id"] = single_not_checked_in.booking_public_id
		return_data_not_checked_in["booking_ref_code"] = single_not_checked_in.booking_ref_code
		return_data_not_checked_in["status"] = single_not_checked_in.booking_status_name
		return_data_not_checked_in["actual_booking_check_in_date"] = single_not_checked_in.actual_booking_check_in_date
		return_data_not_checked_in["booking_url"] ="https://bookings.olpejetaconservancy.org/booking/"+single_not_checked_in.booking_public_id
		not_checked_in.append(return_data_not_checked_in)


	for single_no_cui in get_no_cui:
		return_data_no_cui = {}
		return_data_no_cui["booking_public_id"] = single_no_cui.booking_public_id
		return_data_no_cui["booking_ref_code"] = single_no_cui.booking_ref_code
		return_data_no_cui["booking_type_name"] = single_no_cui.booking_type_name
		return_data_no_cui["actual_booking_check_in_date"] = single_no_cui.actual_booking_check_in_date or single_no_cui.booking_check_in_date
		return_data_no_cui["booking_url"] ="https://bookings.olpejetaconservancy.org/booking/"+single_no_cui.booking_public_id
		no_cui.append(return_data_no_cui)

	for single_booking_payment in get_payment_status_bookings:
		
		p_status = single_booking_payment.payment_status 
		if p_status ==1 or p_status == 3:
			pass
		else:
			return_data_payment ={}
			return_data_payment["booking_public_id"] = single_booking_payment.booking_public_id
			return_data_payment["booking_ref_code"] = single_booking_payment.booking_ref_code
			return_data_payment["booking_type"] = single_booking_payment.booking_type_name
			return_data_payment["booking_url"] ="https://bookings.olpejetaconservancy.org/booking/"+single_booking_payment.booking_public_id
			if not  p_status:
				return_data_payment["booking_payment_status"] = "Not Paid"
			elif p_status == 4:
				return_data_payment["booking_payment_status"] = "To Invoice"
			elif  p_status==2:
				return_data_payment["booking_payment_status"] = "Incomplete Payment"

			if single_booking_payment.booking_type == "PB001A20":
				get_partner = db.session.query(Partner)\
				.filter(Partner.booking_id == single_booking_payment.booking_public_id)\
				.first()

				if get_partner:
					partner_info = requests.get(
						get_partner_details.format(get_partner.partner_id))
					## Booking in KES
					if single_booking_payment.currency == "162fface-f5f1-41de-913b-d2bb784dda3a":
						return_data_payment["customer_code"] = partner_info.json(
						)["customer_code"]
					## Booking in USD
					elif single_booking_payment.currency == "6bf74e49-7ff6-4555-a080-15541d62204a":
						if "customer_code_usd" in partner_info.json():
							return_data_payment["customer_code"] = partner_info.json(
							)["customer_code_usd"]
						else:
							return_data_payment["customer_code"] = "406B036"

			elif single_booking_payment.booking_type == "GB601X10":
				if single_booking_payment.currency == "162fface-f5f1-41de-913b-d2bb784dda3a":
					return_data_payment["customer_code"] = "406B047"
				elif single_booking_payment.currency == "6bf74e49-7ff6-4555-a080-15541d62204a":
					return_data_payment["customer_code"] = "406B036"

			else:
				try:
					user_info = {}
					getBookingSessionUser(single_booking_payment.session_id, user_info)
					if user_info["has_account"] == 1:
						if single_booking_payment.currency == "162fface-f5f1-41de-913b-d2bb784dda3a":
							return_data_payment["customer_code"] = user_info["customer_code_kes"]
						## Booking in USD
						elif single_booking_payment.currency == "6bf74e49-7ff6-4555-a080-15541d62204a":
							return_data_payment["customer_code"] = user_info[
								"customer_code_usd"]
					else:
						## Booking in KES
						if single_booking_payment.currency == "162fface-f5f1-41de-913b-d2bb784dda3a":
							return_data_payment["customer_code"] = "406GA001"
						## Booking in USD
						elif single_booking_payment.currency == "6bf74e49-7ff6-4555-a080-15541d62204a":
							return_data_payment["customer_code"] = "406GA002"
				except Exception as e:
					if single_booking_payment.currency == "162fface-f5f1-41de-913b-d2bb784dda3a":
							return_data_payment["customer_code"] = "406GA001"
						## Booking in USD
					elif single_booking_payment.currency == "6bf74e49-7ff6-4555-a080-15541d62204a":
						return_data_payment["customer_code"] = "406GA002"
			payment_status_today.append(return_data_payment)	
	

	
	reminder_data = {
		"today":datetime.now().strftime("%Y-%m-%d"),
		"checkin_today":checkin_today,
		"checkout_today":checkout_today,
		"overstays":overstays,
		"not_checked_in":not_checked_in,
		"payment_status_today":payment_status_today,
		"no_cui":no_cui
}
	with app.app_context():
		sg = sendgrid.SendGridAPIClient(apikey=app.config["SENDGRID_API_KEY"])
		sender = "obtsbookings@olpejetaconservancy.org"
		recipient="obtsbookings@olpejetaconservancy.org"
		from_email = Email(sender)
		to_email = Email(recipient)

		subject = "End Of Day Process Reminder"
		

		content = Content(
				"text/html",
				render_template("booking_endofday_process.html", data=reminder_data))
		mail = Mail(from_email, subject, to_email, content)


	
		try:
			response = sg.client.mail.send.post(request_body=mail.get())
			email_response =[]
			email_response.append(str(response))
			return jsonify({
					"message":
					"Successfuly sent email."
				}), 200

		except Exception as e:
			error_tuple = sys.exc_info()
			trace = traceback.format_exc()
			raise Exception("User email notification: " + str(e) +
							". Trace: " + trace)


def endOfDayMorning():
	yesterday_datetime = datetime.today() - timedelta(days=1)
	yesterday = yesterday_datetime.strftime("%Y-%m-%d")
	get_checkIn_bookings = db.session.query(Booking)\
		.filter(Booking.deletion_marker == None)\
		.filter(Booking.actual_booking_check_in_date == None)\
		.filter(Booking.checked_in == None)\
		.filter(Booking.booking_check_in_date == yesterday)\
		.order_by(Booking.booking_id.desc())\
		.all()
	get_checkOut_bookings = db.session.query(Booking)\
		.filter(Booking.deletion_marker == None)\
		.filter(Booking.actual_booking_check_out_date == None)\
		.filter(Booking.checked_out == None)\
		.filter(Booking.booking_check_out_date == yesterday)\
		.order_by(Booking.booking_id.desc())\
		.all()
	get_payment_status_bookings = db.session.query(Booking)\
	 .join(BookingGuest, Booking.booking_public_id == BookingGuest.booking_id)\
	 .join(BookingType, Booking.booking_type == BookingType.booking_type_public_id)\
	 .join(BookingStatus, Booking.status == BookingStatus.booking_status_public_id)\
	 .add_columns(Booking.booking_public_id, Booking.booking_type, Booking.booking_check_in_date,\
	  Booking.booking_check_out_date, Booking.actual_booking_check_in_date, Booking.actual_booking_check_out_date,\
	  Booking.booking_done_by, Booking.checked_in, Booking.checked_out, Booking.session_id,\
	  Booking.created_at, Booking.updated_at, Booking.status, Booking.payment_status, Booking.booking_ref_code,\
	   Booking.currency,\
	  BookingType.booking_type_name,\
	  BookingStatus.booking_status_name)\
	 .filter(Booking.deletion_marker == None)\
	 .filter(Booking.booking_check_in_date == yesterday)\
	 .order_by(Booking.booking_id.desc())\
	 .all()
	
	checkin_today = []
	checkout_today =[]
	payment_status_today = []

	
	for single_check_in in get_checkIn_bookings:
		return_data_checkin = {}
		return_data_checkin["booking_public_id"] = single_check_in.booking_public_id
		return_data_checkin["booking_ref_code"] = single_check_in.booking_ref_code
		return_data_checkin["booking_url"] ="https://bookings.olpejetaconservancy.org/booking/"+single_check_in.booking_public_id
		checkin_today.append(return_data_checkin)

	for single_check_out in get_checkOut_bookings:
		return_data_checkout = {}
		return_data_checkout["booking_public_id"] = single_check_out.booking_public_id
		return_data_checkout["booking_ref_code"] = single_check_out.booking_ref_code
		return_data_checkout["booking_url"] ="https://bookings.olpejetaconservancy.org/booking/"+single_check_out.booking_public_id
		checkout_today.append(return_data_checkout)

	for single_booking_payment in get_payment_status_bookings:
		
		p_status = single_booking_payment.payment_status 
		if p_status ==1 or p_status == 3:
			pass
		else:
			return_data_payment ={}
			return_data_payment["booking_public_id"] = single_booking_payment.booking_public_id
			return_data_payment["booking_ref_code"] = single_booking_payment.booking_ref_code
			return_data_payment["booking_type"] = single_booking_payment.booking_type_name
			return_data_payment["booking_url"] ="https://bookings.olpejetaconservancy.org/booking/"+single_booking_payment.booking_public_id
			if not  p_status:
				return_data_payment["booking_payment_status"] = "Not Paid"
			elif p_status == 4:
				return_data_payment["booking_payment_status"] = "To Invoice"
			elif  p_status==2:
				return_data_payment["booking_payment_status"] = "Incomplete Payment"
		
			if single_booking_payment.booking_type == "PB001A20":
				get_partner = db.session.query(Partner)\
				.filter(Partner.booking_id == single_booking_payment.booking_public_id)\
				.first()

				if get_partner:
					partner_info = requests.get(
						get_partner_details.format(get_partner.partner_id))
					## Booking in KES
					if single_booking_payment.currency == "162fface-f5f1-41de-913b-d2bb784dda3a":
						return_data_payment["customer_code"] = partner_info.json(
						)["customer_code"]
					## Booking in USD
					elif single_booking_payment.currency == "6bf74e49-7ff6-4555-a080-15541d62204a":
						if "customer_code_usd" in partner_info.json():
							return_data_payment["customer_code"] = partner_info.json(
							)["customer_code_usd"]
						else:
							return_data_payment["customer_code"] = "406B036"

			elif single_booking_payment.booking_type == "GB601X10":
				if single_booking_payment.currency == "162fface-f5f1-41de-913b-d2bb784dda3a":
					return_data_payment["customer_code"] = "406B047"
				elif single_booking_payment.currency == "6bf74e49-7ff6-4555-a080-15541d62204a":
					return_data_payment["customer_code"] = "406B036"

			else:
				try:
					user_info = {}
					getBookingSessionUser(single_booking_payment.session_id, user_info)
					if user_info["has_account"] == 1:
						if single_booking_payment.currency == "162fface-f5f1-41de-913b-d2bb784dda3a":
							return_data_payment["customer_code"] = user_info["customer_code_kes"]
						## Booking in USD
						elif single_booking_payment.currency == "6bf74e49-7ff6-4555-a080-15541d62204a":
							return_data_payment["customer_code"] = user_info[
								"customer_code_usd"]
					else:
						## Booking in KES
						if single_booking_payment.currency == "162fface-f5f1-41de-913b-d2bb784dda3a":
							return_data_payment["customer_code"] = "406GA001"
						## Booking in USD
						elif single_booking_payment.currency == "6bf74e49-7ff6-4555-a080-15541d62204a":
							return_data_payment["customer_code"] = "406GA002"
				except Exception as e:
					if single_booking_payment.currency == "162fface-f5f1-41de-913b-d2bb784dda3a":
							return_data_payment["customer_code"] = "406GA001"
						## Booking in USD
					elif single_booking_payment.currency == "6bf74e49-7ff6-4555-a080-15541d62204a":
						return_data_payment["customer_code"] = "406GA002"
			payment_status_today.append(return_data_payment)	
	

	
	reminder_data = {
		"today":datetime.now().strftime("%Y-%m-%d"),
		"checkin_today":checkin_today,
		"checkout_today":checkout_today,
		"payment_status_today":payment_status_today
}
	
	with app.app_context():
		sg = sendgrid.SendGridAPIClient(apikey=app.config["SENDGRID_API_KEY"])
		sender = "patricia.kanana@@olpejetaconservancy.org"
		recipient="obtsbookings@olpejetaconservancy.org"
		from_email = Email(sender)
		to_email = Email(recipient)
		subject = "End Of Day Process Reminder"
		email_response =[]
		content = Content("text/html", render_template("booking_endofday_process.html", data = reminder_data))
		mail = Mail(from_email, subject, to_email, content)


	
	try:
		response = sg.client.mail.send.post(request_body=mail.get())

		email_response.append(str(response))
		return jsonify({
				"message":
				"Successfuly sent email."
			}), 200

	except Exception as e:
		
		error_tuple = sys.exc_info()
		trace = traceback.format_exc()
		raise Exception("User email notification: " + str(e) +
						". Trace: " + trace)
	
  