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

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

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, \
from scripts.common.config import KL_BOT_MONGO_COLLECTION, KL_BOT_JOB_COLLECTION, EMAIL_ID, \
    EMAIL_PASSWORD, MONGO_URI, MONGO_SERVICE_DB, mongo_host, mongo_port
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)

from scripts.utils import mongo_utility
print(mongo_port,mongo_host)
my_obj = mongo_utility.MongoUtility(mongo_host, mongo_port)

# klbot_collection = MONGO_DB_OBJ[KL_BOT_MONGO_COLLECTION]
# job_collection = MONGO_DB_OBJ[KL_BOT_JOB_COLLECTION]
q = queue.Queue()
retry_queue = queue.Queue()


def insert_job(job):
    jobValue = {
        "insertedOn": datetime.now(),
        "updatedOn": datetime.now(),
        "status": "Queued"
    }
    jobValue.update(job)
    logger.info("job inserted")
    # job_collection.insert(jobValue)
    my_obj.insert_one(jobValue, MONGO_SERVICE_DB, KL_BOT_JOB_COLLECTION)
    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})
    my_obj.update_one(myQuery, jobValue, MONGO_SERVICE_DB, KL_BOT_JOB_COLLECTION)
    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)
                my_obj.insert_one(item, MONGO_SERVICE_DB, KL_BOT_MONGO_COLLECTION)
            else:
                update_job(item, "Failed")
                item["sentmail"] = False
                # klbot_collection.insert(item)
                my_obj.insert_one(item, MONGO_SERVICE_DB, KL_BOT_MONGO_COLLECTION)
        except:
            pass


def send_email(content, attach=False):
    from_address = EMAIL_ID
    to_address = ["sales@knowledgelens.com", "sneha@knowledgelens.com", "dasharatha.vamshi@knowledgelens.com"]
    # to_address = ["dasharatha.vamshi@knowledgelens.com"]
    msg = MIMEMultipart()
    msg['From'] = from_address
    msg['To'] = " ,".join(to_address)
    filename = ""
    smtp_server = "smtp.gmail.com"
    username = EMAIL_ID
    password = EMAIL_PASSWORD
    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()
