from flask import Flask, request, make_response, jsonify, send_file, abort
from flask_httpauth import HTTPBasicAuth
from flask_mysqldb import MySQL
import logging
from datetime import datetime, timedelta
import pandas as pd
from dateutil import parser
from configparser import ConfigParser
import sqlalchemy as db
import os
import requests
from elasticsearch import Elasticsearch
import urllib.parse
from requests_futures.sessions import FuturesSession
from concurrent.futures import ThreadPoolExecutor
import random
import math


logging.basicConfig(filename='/var/www/html/logs/failed_blasts.log',
                    filemode='a',
                    format='%(asctime)s %(name)s %(levelname)s %(message)s',
                    level=logging.INFO)

#Read config.ini file
config_object = ConfigParser()
config_object.read("config.ini")

#Get info
live_hellio_info = config_object["live_hellio"]
live_hellio_wr = config_object["live_hellio_wr"]
sandbox_wr_info = config_object["sandbox_write"]
authinfo = config_object["auth"]
siteinfo = config_object["url"]
savepathinfo = config_object["savepath"]
elasticinfo = config_object["elastic"]
resendinfo = config_object["resend"]

app = Flask(__name__)
app.config['UPLOAD_EXTENSIONS'] = ['.txt', '.csv', '.xlsx']

mysql = MySQL(app)

auth = HTTPBasicAuth()

USER_DATA = {
    str(authinfo["username"]): str(authinfo["password"])   
}

@auth.verify_password
def verify(username, password):
    if not (username and password):
        return False
    return USER_DATA.get(username) == password

@app.route('/failed/blasts', methods=['POST', 'GET'])
@auth.login_required
def failedBlasts():

    if request.method == 'POST':
        req = request.get_json()
        file_path = str(req['file_path'])
        cnx_1 = db.create_engine('mysql+pymysql://' + str(live_hellio_info["user"]) + ':' + urllib.parse.quote(str(live_hellio_info["password"])) + '@' + str(live_hellio_info['host']) + ':' + str(live_hellio_info["port"]) + '/' + str(live_hellio_info["db"]))
        conn_1 = cnx_1.connect().execution_options(stream_results=True)
        logging.info(f"[file_path:{file_path}]")

        try:
            query = "SELECT file_path FROM user_jobs WHERE file_path='{}'".format(file_path)
            conn_1.execute(query)
            path = conn_1.fetchone()[0]
            logging.info(type(path))
            logging.info(path)
            if not path:
                return make_response(jsonify(code=404, error='No results'), 200)
            conn_1.close()
            logging.info(f"file_path:{path}")
            path_base = file_path.replace("/var/www/html/", "")
            local_filename = os.path.basename(path)
            save_path = os.path.join(savepathinfo["failed_blasts"], local_filename)
            logging.info(f"filename:{local_filename}")
            file_url = str(siteinfo["failed_blasts"]) + str(path_base)
            logging.info(f"file url:{file_url}")

            # requests.get(file_url)

            req = requests.get(file_url, allow_redirects=True)
            with open(save_path, 'wb') as f:
                f.write(req.content)       
                               
        except Exception as e:
            logging.info(f"request failed")
            logging.info(e)
            conn_1.close()
            return make_response(jsonify(code=404, error='No results'), 200)
            
        return make_response(jsonify(code=200, file_path=save_path), 200) 





        
 # resend sms       
@app.route('/resend/sms', methods=['POST', 'GET'])
@auth.login_required
def resendSms():
    es = Elasticsearch(str(elasticinfo["live"]))
    session = FuturesSession(executor=ThreadPoolExecutor(max_workers=10))

    cnx_1 = db.create_engine('mysql+pymysql://' + str(live_hellio_info["user"]) + ':' + urllib.parse.quote(str(live_hellio_info["password"])) + '@' + str(live_hellio_info['host']) + ':' + str(live_hellio_info["port"]) + '/' + str(live_hellio_info["db"]))
    conn_1 = cnx_1.connect().execution_options(stream_results=True)

    cnx_2 = db.create_engine('mysql+pymysql://' + str(live_hellio_wr["user"]) + ':' + urllib.parse.quote(str(live_hellio_wr["password"])) + '@' + str(live_hellio_wr['host']) + ':' + str(live_hellio_wr["port"]) + '/' + str(live_hellio_wr["db"]))
    conn_2 = cnx_2.connect().execution_options(stream_results=True)
    row = {}


    def resend_sms(row, message_type, flash_type):
        dlr = f"{resendinfo['dlr']}?source=%P&destination=%p&SVC=%n&msgID=%F&msg=%a&msglen=%L&timestamp=%t&status=%d&smsc=%i&smsid=%I&dlrv=%d&MDS=%D&DLRS=%A&osms=%b&mid=" + str(row['id']);
        dlr = urllib.parse.quote(dlr)
        message = urllib.parse.quote(row['message'])

        sender = urllib.parse.quote(row['sender'])

        url_text = f"{resendinfo['host']}?username=" + str(row['bpid']) + str(resendinfo['password']) + '&to=' + str(
            row['msisdn']) + '&from=' + str(sender) + '&text=' + str(message) + '&dlr-mask=27&dlr-url=' + str(dlr)+'&account=' + str(row['id'])
        url_unicode = f"{resendinfo['host']}?username=" + str(row['bpid']) + str(resendinfo['password']) + '&to=' + str(
            row['msisdn']) + '&from=' + str(sender) + '&text=' + str(message) + '&charset=UTF-8&coding=2&dlr-mask=27&dlr-url=' + str(dlr)+'&account=' + str(row['id'])

        url_text_flash = f"{resendinfo['host']}?username=" + str(row['bpid']) + str(resendinfo['password']) + '&to=' + str(
            row['msisdn']) + '&from=' + str(sender) + '&text=' + str(message) + '&mclass=0&dlr-mask=27&dlr-url=' + str(dlr)+'&account=' + str(row['id'])
        url_unicode_flash = f"{resendinfo['host']}?username=" + str(row['bpid']) + str(resendinfo['password']) + '&to=' + str(
            row['msisdn']) + '&from=' + str(sender) + '&text=' + str(message) + '&mclass=0&charset=UTF-8&coding=2&dlr-mask=27&dlr-url=' + str(dlr)+'&account=' + str(row['id'])


        try:
            if flash_type.lower().strip() == 'flash':
                if message_type.lower().strip() == 'unicode':
                    url = url_unicode_flash
                else:
                    url = url_text_flash
            else:
                if message_type.lower().strip() == 'unicode':
                    url = url_unicode
                else:
                    url = url_text
        except:
            url = url_text
        session.get(url)
        logging.info("[status:Sent] [job_id:{job_id}] [username:{username}] [route:{bpid}] [msisdn:{msisdn}] [sender_id:{sender}] [sms_id:{id}] [sms_count:{sms_count}] [message:{message}]".format(job_id=str(row['job_id']),username=str(row['username']),bpid=str(row['bpid']),msisdn=str(row['msisdn']),sender=row['sender'],id=str(row['id']),sms_count=str(row['sms_count']), message=str(row['message'].replace("\n", " "))))

        return

    # randomly generate 2 digits
    def resend_id():
        digits = "0123456789"
        suffix = ''
        for i in range(2) :
            suffix += digits[math.floor(random.random() * 10)]   
        return suffix

    if request.method == 'POST':
        req = request.get_json()
        logging.info(f'request_object:{req}')
        username = req['username']
        message_id = str(req['message_id'])
        message_type = req['message_type']
        flash_type = req['flash_type']
        
        
        json_payload = {
                                "query": {
                                    "match": {"id.keyword":message_id}
                                }   
                            }
        try:   
            query = "SELECT username from logs where id='{}'".format(message_id)
            query_result = conn_1.execute(query)
            try:
                ver_username = query_result.first()[0]
            except:
                return make_response(jsonify(code=403, error="{} has no such ID"), 200)
            ver_username = str(ver_username)
            logging.info(f'username : {username}')
            logging.info(f'verified username:{ver_username}')
            if username.lower() == ver_username.lower():
                res = es.search(index="deywuro-logs-*", body=json_payload)
                if res['hits']['hits']:  
                    row = dict(
                        id=res['hits']['hits'][0]['_source']['id'],
                        job_id=res['hits']['hits'][0]['_source']['job_id'],
                        user_id=res['hits']['hits'][0]['_source']['user_id'],
                        bpid=res['hits']['hits'][0]['_source']['bpid'],
                        username=res['hits']['hits'][0]['_source']['username'],
                        h_message = res['hits']['hits'][0]['_source']['h_message'],
                        msisdn=res['hits']['hits'][0]['_source']['msisdn'],
                        network=res['hits']['hits'][0]['_source']['network'],
                        sender=res['hits']['hits'][0]['_source']['sender'],
                        message=res['hits']['hits'][0]['_source']['message'],
                        sms_count=res['hits']['hits'][0]['_source']['sms_count'],
                        submit_date=res['hits']['hits'][0]['_source']['submit_date'],
                        delivery_date=res['hits']['hits'][0]['_source']['delivery_date'],
                        msgid=res['hits']['hits'][0]['_source']['msgid'],
                        response=res['hits']['hits'][0]['_source']['response'],
                        refid=res['hits']['hits'][0]['_source']['refid'],
                        network_id=res['hits']['hits'][0]['_source']['network_id'],
                        sms_price=res['hits']['hits'][0]['_source']['sms_price'],
                        status=res['hits']['hits'][0]['_source']['status'],
                        created_by=res['hits']['hits'][0]['_source']['created_by'],
                        originated=res['hits']['hits'][0]['_source']['originated'],
                        created_at=res['hits']['hits'][0]['_source']['created_at'],
                        updated_at=res['hits']['hits'][0]['_source']['updated_at']     
                    )
                    
                    suffix = resend_id()
                    row['id'] = "resend_" + str(row['id']) + '_' + suffix    
                    query = "INSERT INTO logs(id, job_id, user_id, bpid, username, msisdn, network, sender, h_message, message, sms_count, submit_date, delivery_date, status, created_by, response, msgid, originated, refid, created_at, updated_at, network_id, sms_price) VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
                    val = (row['id'], row['job_id'], row['user_id'], row['bpid'], row['username'], row['msisdn'], row['network'], row['sender'], row['h_message'], row['message'], row['sms_count'], row['submit_date'], row['delivery_date'], row['status'], row['created_by'], row['response'], row['msgid'], row['originated'], row['refid'], row['created_at'], row['updated_at'], row['network_id'], row['sms_price'])
                    conn_2.execute(query, val)
                    conn_2.close()
                    resend_sms(row, message_type, flash_type)

                else:
                    conn_1.close()
                    conn_2.close()
                    return make_response(jsonify(code=404, error='No results'), 200)

            else:
                conn_1.close()
                conn_2.close()
                return make_response(jsonify(code=403, error="{} has no such ID"), 200)
            
        except Exception as e:
            conn_1.close()
            conn_2.close()
            logging.info(f'failed with error {e}')
            return make_response(jsonify(code=500, error='search failed'), 200)
        return make_response(jsonify(code=200, success='success'), 200)


if __name__ =='__main__':
    app.run(host='0.0.0.0')

