import queue
import traceback
import traceback
import uuid
import ssl
import smtplib
from datetime import datetime
from email import encoders
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from threading import Thread

from flask import request, Blueprint, jsonify
from flask_restplus import Resource, Api
from pymongo import MongoClient

from models.model import *
from scripts.common.config import ATTENDANCE_MONGO_HOST, ATTENDANCE_MONGO_PORT, ATTENDANCE_MONGO_DATABASE, \
    ATTENDANCE_MONGO_AUTH, ATTENDANCE_MONGO_USERNAME, ATTENDANCE_MONGO_PASSWORD, \
    KL_BOT_MONGO_COLLECTION, KL_BOT_JOB_COLLECTION
from scripts.common.logsetup import logger
from scripts.constants.app_constants import APIEndPoints, RequestMethods

klbot_blueprint = Blueprint('klbot_services', __name__)
api = Api(klbot_blueprint)
api.add_namespace(klbot_namespace)

if ATTENDANCE_MONGO_AUTH.lower() == 'false:':
    attendance_mongo = MongoClient(ATTENDANCE_MONGO_HOST, int(ATTENDANCE_MONGO_PORT))
else:
    attendance_mongo = MongoClient(host=ATTENDANCE_MONGO_HOST, port=int(ATTENDANCE_MONGO_PORT),
                                   username=ATTENDANCE_MONGO_USERNAME, password=ATTENDANCE_MONGO_PASSWORD)

attendance_database = attendance_mongo[ATTENDANCE_MONGO_DATABASE]
klbot_collection = attendance_database[KL_BOT_MONGO_COLLECTION]
job_collection = attendance_database[KL_BOT_JOB_COLLECTION]
q = queue.Queue()
retry_queue = queue.Queue()


# @invoice_namespace.route(APIEndPoints.list_register)
# class list_register(Resource):
#     def get(self):
#         try:
#             if request.method == RequestMethods.GET:
#                 all_registers = register_collection.find({}, {"_id": 0})
#                 data = {
#                     "status": True,
#                     "message": "success",
#                     "data": [
#
#                     ]
#                 }
#                 for task in all_registers:
#                     # print(task)
#                     task['lastUpdatedTime'] = task['lastUpdatedTime'].strftime("%d-%b-%Y %I:%M %p")
#                     data['data'].append(task)
#                 return jsonify(data)
#         except Exception as e:
#             logger.error(e)
#             traceback.print_exc()
#             return jsonify({'status': False, 'message': str(e)})


def insert_job(job):
    jobValue = {
        "insertedOn": datetime.now(),
        "updatedOn": datetime.now(),
        "status": "Queued"
    }
    jobValue.update(job)
    logger.info("job inserted")
    job_collection.insert(jobValue)

    return "job inserted"


def update_job(job, status):
    myQuery = {'jobId': job["jobId"]}
    jobValue = {
        "jobId": job["jobId"],
        "updatedOn": datetime.now(),
        "status": status,
    }
    logger.info("job updated")
    job_collection.update_one(myQuery, {"$set": jobValue})
    return "job updated inserted"


def add_to_queue(user_details):
    job = {
        "jobId": str(uuid.uuid1()).split('-')[0]
    }
    job.update(user_details)
    q.put(job)
    logger.info("job added to queue")
    x = insert_job(job)
    return job


def my_process():
    while True:
        try:
            item = q.get()
            if item is None:
                continue
            update_job(item, "Inprogress")
            my_dict = {}
            stringval = ""
            for key, value in item.items():
                if value is not None and key != "jobId" and key != "clinetId":
                    stringval = stringval + str(key).capitalize() + " : " + value + " , "
            mail_dict = {'subject': item['request'], 'body': stringval[0:len(stringval)-2]}
            print(mail_dict)
            t = send_email(mail_dict)
            if t:
                update_job(item, "Completed")
                item["sentmail"] = True
                klbot_collection.insert(item)
            else:
                update_job(item, "Failed")
                item["sentmail"] = False
                klbot_collection.insert(item)
        except:
            pass


def send_email(content, attach=False):
    from_address = "dasharatha.vamshi@knowledgelens.com"
    to_address = ["sales@knowledgelens.com", "sneha@knowledgelens.com", "dasharatha.vamshi@knowledgelens.com"]
    msg = MIMEMultipart()
    msg['From'] = from_address
    msg['To'] = " ,".join(to_address)
    filename = ""
    smtp_server = "smtp.gmail.com"
    username = "dasharatha.vamshi@knowledgelens.com"
    password = "Salla$230999"
    smtp_server_port = 587
    ssl_key = False
    try:
        msg['Subject'] = "KL Bot: " + content['subject']
        msg['body'] = content['body']
        msg.attach(MIMEText(msg['body'], 'plain'))

        # give filename in self.filename to attach a document.
        if attach:
            attachment = open(filename, "rb")
            p = MIMEBase('application', 'octet-stream')
            p.set_payload(attachment.read())
            encoders.encode_base64(p)
            p.add_header('Content-Disposition', "attachment; filename= %s" % filename)
            msg.attach(p)

        # starting the sever
        if ssl_key:
            context = ssl.create_default_context()
            with smtplib.SMTP_SSL(smtp_server, smtp_server_port, context=context) as server:
                server.login(username, password)
                server.sendmail(from_address, to_address, msg.as_string())
        else:
            s = smtplib.SMTP(smtp_server, smtp_server_port)
            s.starttls()
            s.login(username, password)
            s.sendmail(from_address, to_address, msg.as_string())
            s.quit()
        return True
    except Exception as e:
        print(e)
        return False


@klbot_namespace.route(APIEndPoints.insert_to_mongo)
class insert_to_mongo(Resource):
    @api.expect(insert_to_mongo)
    def post(self):
        try:
            if request.method == RequestMethods.POST:
                content = request.get_json()
                userID = str(uuid.uuid1()).split('-')[0]
                user_details = {
                    "clinetId": userID,
                    "request": content.get("request", None),
                    "name": content.get("name", None),
                    "email": content.get("email", None),
                    "phoneNumber": content.get("phoneNumber", None),
                    "company": content.get("company", None),
                    "query": content.get("query", None),
                    "product": content.get("product", None),
                }
                # klbot_collection.insert(user_details)
                job = add_to_queue(user_details)
                # t = Thread(target=my_process)
                # t.start()
                return jsonify(
                    {"status": True, "message": "Client registered successfully", "job": job["jobId"]})
        except Exception as e:
            logger.error(e)
            traceback.print_exc()
            return jsonify({'status': False, 'message': str(e)})


def init_thread():
    t = Thread(target=my_process)
    t.start()
