import flask
from flask import jsonify, request
import requests
from flask_cors import CORS,cross_origin
from OpenSSL import SSL
import boto3
from botocore.exceptions import ClientError
import time
from datetime import datetime
from pytz import timezone
import urllib
import whisper
import whisper_timestamped
import moviepy.editor as mp
from pydub import AudioSegment
from pydub.silence import detect_silence, detect_nonsilent
import json
import collections
from collections import defaultdict
import re
import string
import cv2
import os
import numpy as np
import ssl
import mysql.connector
from gaze_tracking import GazeTracking
from config import *

# context = SSL.Context(SSL.TLSv1_2_METHOD)
# context.use_privatekey_file('./crt/privatekey.pem')
# context.use_certificate_file('./crt/fullchain.pem')

ssl._create_default_https_context = ssl._create_unverified_context

app = flask.Flask(__name__)
CORS(app)


@app.route('/', methods = ['GET'])
@cross_origin()
def hello():
    # return "Hello, Python233!!"
    # os.environ['CURL_CA_BUNDLE']=""
    # session = requests.Session()
    # session.verify = False
    # HOST = DB_host
    # USER = DB_user
    # PASSWORD = DB_password
    # DATABASE = DB_name

    try:
        secret_name = "aws-secret"
        region_name = "us-east-1"

        # Create a Secrets Manager client
        session = boto3.session.Session()
        client = session.client(
            service_name='secretsmanager',
            region_name=region_name
        )

        try:
            get_secret_value_response = client.get_secret_value(
                SecretId=secret_name
            )

            get_secret_value_db = client.get_secret_value(
                SecretId='live-db'
            )
        except ClientError as e:
            # For a list of exceptions thrown, see
            # https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
            raise e

        secret = get_secret_value_response['SecretString']
        secrt = json.loads(secret)

        secret_db = get_secret_value_db['SecretString']
        secrt_db = json.loads(secret_db)

        # mydb = mysql.connector.connect(
        #     host=secrt_db['db_host'],
        #     user=secrt_db['db_user'],
        #     password=secrt_db['db_pass'],
        #     database=secrt_db['db_name']
        #     )
        mydb = mysql.connector.connect(
            host='mip-prod-mysql.c87oewlzrnhl.us-east-1.rds.amazonaws.com',
            user='mip_prod_mysql',
            password='cNzymZll*2RTD41u',
            database='mip_prod_mysql'
            )

        print(mydb) 
        cursor = mydb.cursor()
        sql_check_query = "SELECT * FROM mip_ai_feedback_queue_tbl WHERE status = '1'"
        cursor.execute(sql_check_query)
        records = cursor.fetchall()
        print("Continue satus rows in table: ", cursor.rowcount)
        if cursor.rowcount == 0:
            sql_select_Query = "SELECT * FROM mip_ai_feedback_queue_tbl WHERE status = '0' AND data_process = '1' ORDER BY created_at ASC LIMIT 1"
            cursor.execute(sql_select_Query)

            records = cursor.fetchall()
            print("Total number of rows in table: ", cursor.rowcount)
            if cursor.rowcount > 0:
                for row in records:
                    result_db = row[0]
                
                # start process time
                now_utc = datetime.now(timezone('America/Los_Angeles'))
                start_time = now_utc.strftime("%Y-%m-%d %H:%M:%S") 
                print(start_time)  
                
                sql_update_Query = "UPDATE mip_ai_feedback_queue_tbl SET status = '1', process_start_time = '"+start_time+"' WHERE id = '"+result_db+"'"
                cursor.execute(sql_update_Query)
                mydb.commit()
                print(cursor.rowcount, "record(s) affected") 
                print(result_db)
                
                video_path = row[1]
                user_id = row[2]
                interview_id = row[3]
                question_id = row[4]
                interview_type = row[5]
            
            # video_path = request.args.get('video')
            # user_id = request.args.get('user_id')
            # interview_id = request.args.get('interview_id')
            # question_id = request.args.get('question_id')
            # interview_type = request.args.get('type')

                split_name = os.path.splitext(video_path)[0]
                # access_key_id = AWS_ACCESS_KEY_ID
                # secret_access_key = AWS_SECRET_ACCESS_KEY
                # region_name = REGION_NAME
                
                try:
                    s3 = boto3.client('s3', 
                                    aws_access_key_id=secrt['AWS_ACCESS_KEY_ID'],
                                    aws_secret_access_key=secrt['AWS_SECRET_ACCESS_KEY'], 
                                    region_name=REGION_NAME)
                    BUCKET_NAME = 'pub.myinterviewpractice.com'
                except Exception as e:
                    print(f"Error creating S3 client: {e}")
                
                try:
                    url = s3.generate_presigned_url(
                        ClientMethod='get_object',
                        Params={
                            'Bucket': BUCKET_NAME,
                            'Key': 'live/' + video_path
                        }
                    )
                    if video_path.endswith(".mp3"):
                        aud_file = s3.download_file( 
                            Filename="audio_files/"+video_path, 
                            Bucket= BUCKET_NAME,
                            Key= 'live/' + video_path
                            
                        )
                        # print(aud_file)
                    
                    # def transcribe_file(job_name, file_uri, transcribe_client):
                    #     transcribe_client.start_transcription_job(
                    #         TranscriptionJobName=job_name,
                    #         Media={'MediaFileUri': file_uri},
                    #         MediaFormat='mp4',
                    #         LanguageCode='en-US'
                    #     )

                    #     max_tries = 60
                    #     while max_tries > 0:
                    #         max_tries -= 1
                    #         job = transcribe_client.get_transcription_job(TranscriptionJobName=job_name)
                    #         job_status = job['TranscriptionJob']['TranscriptionJobStatus']
                    #         if job_status in ['COMPLETED', 'FAILED']:
                    #             print(f"Job {job_name} is {job_status}.")
                    #             if job_status == 'COMPLETED':
                    #                 response = urllib.request.urlopen(job['TranscriptionJob']['Transcript']['TranscriptFileUri'])
                    #                 data = json.loads(response.read())
                    #                 text = data['results']['transcripts'][0]['transcript']
                    #                 return text
                    #             break
                    #         else:
                    #             print(f"Waiting for {job_name}. Current status is {job_status}.")
                    #         time.sleep(10)

                    # file_uri = ('s3://images.myinterviewpractice.com/ai_test/' + video_path)
                    
                    err_audio = 0
                    er_movie = 0
                    reslt = ''
                    time_au = 0
                    audio_vol = 0
                    total_words = 0
                    pace = 0
                    vol = ''
                    puse = 0
                    arr_ps = []
                    new_filler = 0
                    new_total_power_count = 0
                    ngtv_count = 0
                    um_count = 0
                    new_f_ar = []
                    filler_count = 0    
                    filler_store = []  
                    filler_time_arr = []
                    filler_word_counts = {}
                    ph_filler_ar = []
                    pfiller_var = 0
                    filler_phrse_word = None
                    filer_phrse = ''
                    ph_filler_wrds = {}
                    power_count = 0    
                    power_store = []
                    power_time_arr = []
                    power_word_counts = {}
                    ph_power_ar = []
                    ph_power_var = 0
                    power_phrse_word = None
                    ph_power_wrds = {}
                    powr_phrse = ''
                    ngtv_count = 0    
                    ngtv_store = []
                    ngtv_time_arr = []  
                    ngtv_word_counts = {}
                    um_count = 0    
                    um_store = []
                    um_time_arr = []  
                    um_word_counts = {}
                    um_time = ''
                    ngtv_time = ''
                    filr_time = ''
                    pwr_time = ''
                    total_filler_words = 0
                    total_power_words = 0
                    new_p_ar = []
                    new_n_ar = []
                    err_eye = 0
                    err_smle = 0
                    arr1 = 0
                    lght = ''
                    cntr = 0
                    lft = 0
                    rght = 0
                    count_s = 0
                    smile_count = 0
                    dis_total_eye_percentage = 0
                    per_eye_contact_center = 0
                    per_eye_contact_left = 0
                    per_eye_contact_right = 0
                    dis_total_smile_percentage = 0
                    eye_contact_behav = ""


                    try:
                        audio = whisper_timestamped.load_audio(url)
                        model = whisper_timestamped.load_model("base", device="cpu")
                        result = whisper_timestamped.transcribe(model,audio,beam_size=5,best_of=5)
                        reslt = (result)
                        rs = json.dumps(reslt, indent = 1)
                        curr_time = time.localtime() 
                        end_time = time.strftime("%H-%M-%S", curr_time) 
                        # rs_aws = transcribe_file( split_name + '-job' + end_time, file_uri, transcribe_client)
                        # print("Video CC:",rs_aws)
                        # print(rs)

                        def unique(list1):
                    
                            # insert the list to the set
                            list_set = set(list1)
                            # convert the set to the list
                            unique_list = (list(list_set))
                            u_ar = []
                            for x in unique_list:
                                u_ar.append(x)
                            print (u_ar)
                            combined_data = defaultdict(list)
                            for word, value in u_ar:
                                combined_data[word].append(value)
                                combined_data[word].sort()
                            
                            # Convert the dictionary to a list of lists
                            new_ar = [{key : values} for key, values in combined_data.items()]
                            # obg[]
                            print(new_ar)
                            return new_ar

                        def convert_to_preferred_format(sec):
                            sec = sec % (24 * 3600)
                            hour = sec // 3600
                            sec %= 3600
                            min = sec // 60
                            sec %= 60
                            # print("seconds value in hours:",hour)
                            # print("seconds value in minutes:",min)
                            return "%2d:%02d" % (min, sec)        

                        # search filler words with timestamp
                        ld = json.loads(rs)
                        with open(r'lib_file/filler.txt','r') as file:
                            filler_con = file.read()
                        with open(r'lib_file/filler_phrase.txt','r') as file:
                            filler_phrse = file.read()
                            ph_filler = filler_phrse.split(',')
                        with open(r'lib_file/power.txt','r') as file:
                            power_con = file.read()
                        with open(r'lib_file/power_phrase.txt','r') as file:
                            power_phrse = file.read()
                            ph_power = power_phrse.split(',')
                        with open(r'lib_file/negative.txt','r') as file:
                            ngtv_con = file.read()
                        with open(r'lib_file/um_words.txt','r') as file:
                            um_con = file.read()

                        
                        for i in range(0, len(ld['segments'])):
                            txt = ld['segments'][i]['text']
                            txt_lwr = txt.lower()
                            # print(txt)
                            
                            new_s = txt_lwr.translate(str.maketrans('', '', string.punctuation))
                            # print(new_s)
                            for word in new_s.split():
                                # print(word)
                                for w in filler_con.split(','):
                                    if word == w:
                                        filler_count += 1
                                        filler_store.append(word)
                                        if filler_count > 0:
                                            # print(filler_count) 
                                            for j in range(0, len(ld['segments'][i]['words'])):
                                                wrd = ld['segments'][i]['words'][j]['text']
                                                wrd_lwr = wrd.lower()
                                                new_w = wrd_lwr.translate(str.maketrans('', '', string.punctuation))
                                                if new_w == w:
                                                    pfc_lwr = (ld['segments'][i]['words'][j]['text']).lower()
                                                    pfc_txt = pfc_lwr.translate(str.maketrans('', '', string.punctuation))
                                                    filr_time = (pfc_txt,(convert_to_preferred_format(ld['segments'][i]['words'][j]['start'])))
                                                    filler_time_arr.append(filr_time)
                                                    # print(ld['segments'][i]['words'][j]['text'],ld['segments'][i]['words'][j]['start'])
                                            filler_word_counts = collections.Counter(filler_store)
                        new_f_ar = []
                        list1 = filler_time_arr
                        new_f_ar = unique(list1)
                        print(filler_count)
                        if filler_count == 0:
                            print(filler_count)
                            print('No Filler Words')
                        
                        for pi in range(0, len(ld['segments'])):
                            p_txt = ld['segments'][pi]['text']
                            p_txt_lwr = p_txt.lower()
                            # print(txt)
                            
                            new_ps = p_txt_lwr.translate(str.maketrans('', '', string.punctuation))
                            # print(new_s)
                            for pword in new_ps.split():    
                            
                                for p in power_con.split(','):
                                    if pword == p:
                                        power_count += 1
                                        power_store.append(pword)
                                        if power_count > 0:
                                            # print(power_count) 
                                            for k in range(0, len(ld['segments'][pi]['words'])):
                                                p_wrd = ld['segments'][pi]['words'][k]['text']
                                                p_wrd_lwr = p_wrd.lower()
                                                new_pw = p_wrd_lwr.translate(str.maketrans('', '', string.punctuation))
                                                if new_pw == p:
                                                    ppc_lwr = (ld['segments'][pi]['words'][k]['text']).lower()
                                                    ppc_txt = ppc_lwr.translate(str.maketrans('', '', string.punctuation))
                                                    pwr_time = (ppc_txt,(convert_to_preferred_format(ld['segments'][pi]['words'][k]['start'])))
                                                    power_time_arr.append(pwr_time)
                                                    # print(ld['segments'][pi]['words'][k]['text'],ld['segments'][pi]['words'][k]['start'])
                                            power_word_counts = collections.Counter(power_store)
                        new_p_ar = []
                        list2 = power_time_arr
                        new_p_ar = unique(list2)
                        print(power_count)
                        if power_count == 0:
                            print(power_count)
                            print('No Power Words')
                        for ni in range(0, len(ld['segments'])):
                            n_txt = ld['segments'][ni]['text']
                            n_txt_lwr = n_txt.lower()
                            # print(txt)
                            
                            new_ns = n_txt_lwr.translate(str.maketrans('', '', string.punctuation))
                            # print(new_s)
                            for nword in new_ns.split():                
                                
                                for n in ngtv_con.split(','):
                                    if nword == n:
                                        ngtv_count += 1
                                        ngtv_store.append(nword)
                                        if ngtv_count > 0:
                                            # print(ngtv_count) 
                                            for l in range(0, len(ld['segments'][ni]['words'])):
                                                n_wrd = ld['segments'][ni]['words'][l]['text']
                                                n_wrd_lwr = n_wrd.lower()
                                                new_nw = n_wrd_lwr.translate(str.maketrans('', '', string.punctuation))
                                                if new_nw == n:
                                                    pnc_lwr = (ld['segments'][ni]['words'][l]['text']).lower()
                                                    pnc_txt = pnc_lwr.translate(str.maketrans('', '', string.punctuation))
                                                    ngtv_time = (pnc_txt,(convert_to_preferred_format(ld['segments'][ni]['words'][l]['start'])))
                                                    ngtv_time_arr.append(ngtv_time)
                                                    # print(ld['segments'][i]['words'][l]['text'],ld['segments'][i]['words'][l]['start'])
                                            ngtv_word_counts = collections.Counter(ngtv_store)    
                        new_n_ar = []
                        list3 = ngtv_time_arr
                        new_n_ar = unique(list3)
                        print(ngtv_count)
                        if ngtv_count == 0:
                            print(ngtv_count)
                            print('No Negative Words')

                        # um counter analysis    
                        for ui in range(0, len(ld['segments'])):
                            u_txt = ld['segments'][ui]['text']
                            u_txt_lwr = u_txt.lower()
                            # print(txt)
                            new_us = u_txt_lwr.translate(str.maketrans('', '', string.punctuation))
                            # print(new_s)
                            for uword in new_us.split():                
                                
                                for u in um_con.split(','):
                                    if uword == u:
                                        um_count += 1
                                        um_store.append(uword)
                                        if um_count > 0:
                                            # print(um_count) 
                                            for m in range(0, len(ld['segments'][ui]['words'])):
                                                u_wrd = ld['segments'][ui]['words'][m]['text']
                                                u_wrd_lwr = u_wrd.lower()
                                                new_uw = u_wrd_lwr.translate(str.maketrans('', '', string.punctuation))
                                                if new_uw == u:
                                                    um_time = (ld['segments'][ui]['words'][m]['text'],ld['segments'][ui]['words'][m]['start'])
                                                    um_time_arr.append(um_time)
                                            um_word_counts = collections.Counter(um_store)    
                        new_u_ar = []
                        list4 = um_time_arr
                        new_u_ar = unique(list4)
                        print(um_count)
                        if um_count == 0:
                            print(um_count)
                            print('No Um Words')
                            
                        # ---------

                        # um analysis using aws transcript
                            
                        # u_txt = rs_aws
                        # u_txt_lwr = u_txt.lower()
                        # # print(txt)
                        # um_time_arr = []
                        # new_us = u_txt_lwr.translate(str.maketrans('', '', string.punctuation))
                        # for uword in new_us.split():
                        #     for u in um_con.split(','): 
                        #         if uword == u:
                        #             um_count += 1
                        #             um_store.append(uword)
                        #             # print(store)
                        #             um_word_counts = collections.Counter(um_store)
                        # if um_count > 0 :
                        #     print(um_word_counts)
                        #     # print(filler_count + pfiller_var) 
                        #     # print(filer_phrse)
                        # else:
                        #     print(um_word_counts)
                        #     print('No Um Words')
                                        
                                
                        print("Filler Count:",filler_word_counts)
                        print("Power Count:",power_word_counts)
                        print("Negative Count:",ngtv_word_counts)
                        print("Um Count:",um_word_counts)
                        reslt = (ld['text'])
                        print(reslt)
                        rslt_lwr = reslt.lower()
                        ph_var = ''
                        f_count = 0
                        f_sum = 0
                        ph_pow_var = ''
                        p_count = 0
                        p_sum = 0
                        # filler phrases detection
                        for a in range(0, len(ph_filler)):
                            new_ph = re.search(ph_filler[a], rslt_lwr)
                            try:
                                filler_phrse_word = new_ph.group()
                                f_count = len(re.findall(filler_phrse_word, rslt_lwr))
                            except AttributeError:
                                continue
                            # print(filler_phrse_word)
                            pfiller_var += 1
                            ph_var = filler_phrse_word.strip()
                            # ph_var = (filler_phrse_word, f_count)
                            data_f={}
                            data_f[filler_phrse_word]=f_count
                            print(data_f)
                            ph_filler_ar.append(data_f)
                            # filer_phrse = collections.Counter(ph_filler_ar)
                            f_sum = f_sum + f_count
                        if pfiller_var > 0:
                            print(ph_filler_ar)
                            print('Total filler Phrase:', f_sum) 
                            ph_filler_wrds = ph_filler_ar
                            total_filler_words = pfiller_var
                        else:
                            total_filler_words = 'No Filler Phrases'

                        # power phrases detection
                        for b in range(0, len(ph_power)):
                            pow_ph = re.search(ph_power[b], rslt_lwr)
                            try:
                                power_phrse_word = pow_ph.group()
                                p_count = len(re.findall(power_phrse_word, rslt_lwr))
                            except AttributeError:
                                continue
                            # print(power_phrse_word)
                            ph_power_var += 1
                            ph_pow_var = power_phrse_word.strip()
                            # ph_pow_var = (power_phrse_word, p_count)
                            data_p={}
                            data_p[ph_pow_var]=p_count
                            print(data_p)
                            ph_power_ar.append(data_p)
                            # powr_phrse = collections.Counter(ph_power_ar)
                            p_sum = p_sum + p_count
                        if ph_power_var > 0:
                            # print(power_phrse) 
                            print('Total Power Phrase:', p_sum)
                            ph_power_wrds = ph_power_ar
                            total_power_words = ph_power_var
                        else:
                            total_power_words = 'No Power Phrases'

                        new_total_filler_count = f_sum + filler_count
                        print("New Total Filler:",new_total_filler_count)
                        new_total_power_count = p_sum + power_count
                        print("New Total Power:",new_total_power_count)

                        # analysis of CC
                        total_words = len(reslt.split())
                        print("Total words spoken:",total_words)
                        new_filler_count = 0
                        new_filler = 0
                        
                        # in 100 words
                        if total_words > 0:
                            new_filler_count = ((new_total_filler_count/total_words)*100)
                            new_filler = (round(new_filler_count,1))
                            print(new_filler)
                    
                    except Exception as e:
                        # error counting
                        err_audio = err_audio + 1
                        print("Error in audio analysis:", err_audio)

                    if video_path.endswith(".mp3"):
                        # total_words = len(reslt.split())
                        # print("Total words spoken:",total_words)
                        
                        # audio analysis
                        file_path = "audio_files/"+video_path
                        audio_format = "mp3"

                        audio = AudioSegment.from_file(file_path, format = audio_format)
                        n = len(audio)
                        tme = (n/1000)
                        time_dec = ((n/1000)/60)
                        # time_min = (str(round(time_dec, 2)) + ' Min')
                        time_au = convert_to_preferred_format(tme)
                        print("Audio Length:",time_au)

                        pace_decimal = (total_words / time_dec)
                        pace = (str(round(pace_decimal , 2)))
                        print("Pace of Speech:",pace)

                        # volume analysis
                        print('Volume in dBFS:',audio.dBFS)
                        audio_vol = (str(round(audio.dBFS, 2)))
                        
                        if audio.dBFS < -60:
                            audio_vol = -100
                        
                        if audio.dBFS > -10:
                            vol = "loud"
                            print(vol)
                        elif audio.dBFS < -10 and audio.dBFS > -30:
                            vol = "Normal"
                            print(vol)
                        elif audio.dBFS < -30:
                            vol = "Low"
                            print(vol)

                        # pause counter
                        audio_pause = []
                        chunk_ar = []
                        arr_ps = []
                        audio_pause_arr = detect_silence(audio, min_silence_len=3200, silence_thresh=-40)
                        for chunks in audio_pause_arr:
                            chunk_ar = ( [convert_to_preferred_format(chunk/1000) for chunk in chunks])
                            # print(chunk_ar)
                            audio_pause.append(chunk_ar)
                        
                        for key, value in audio_pause:
                            # print(key)
                            # print(value)
                            arr_ps.append(key)
                        
                        if not chunk_ar:
                            print("Pause timimg array:", arr_ps)
                        else:
                            print("Pause timimg array bef-pop:", arr_ps)
                            if arr_ps[0] == ' 0:00':
                                arr_ps.pop(0)
                                # print('yes')
                            print("Pause timimg array pop:", arr_ps)
                        puse = len(arr_ps)
                        print("pause:", puse)
                        
                        
                        os.remove('audio_files/'+video_path)   
                        
                        
                        
                        result_text = {"video_cc": reslt, "audio_length": time_au, "audio_volume_dBFS": audio_vol, "total_words_spoken": total_words, "pace_of_speech": pace, "audio_volume": vol, "pause": puse, "pause_timestamp": arr_ps, "filler_word_count": new_filler, "power_word_count": new_total_power_count, "negative_word_count": ngtv_count, "um_word_count": um_count, "filler_word_timestamp": new_f_ar, "filler_count": filler_word_counts, "filler_phrases" :ph_filler_wrds, "filler_phrase_counter" :total_filler_words, "power_phrases" :ph_power_wrds, "power_phrase_counter" :total_power_words, "power_word_timestamp": new_p_ar, "power_count": power_word_counts, "negative_word_timestamp": new_n_ar, "negative_count": ngtv_word_counts, "um_word_timestamp": um_time_arr, "um_count": um_word_counts}
                        # dm_ar = []
                        # dm_ar.append(result_text)
                        
                        # print(dm_ar)
                        new_rsltxt = json.dumps(result_text)
                    
                        mycursor = mydb.cursor()

                        sql = "INSERT INTO mip_ai_generate_feedback_data_tbl (user_id,interview_id,question_id,interview_type,content) VALUES (%s, %s, %s, %s, %s)"
                        val = (user_id, interview_id, question_id, interview_type, new_rsltxt)
                    else:
                        # converting video to audio
                        try:
                            clip = mp.VideoFileClip(r"" + url)
                            clip.audio.write_audiofile(r"audio_files/"+ split_name +".wav")
                            print("Finished the conversion into audio...")
                            
                            # generating CC
                            # model = whisper.load_model("base")
                            # result = model.transcribe("/home/staging/dashboard-staging.myinterviewpractice.com/demo_ai/uploads/" + video_path , fp16=False)
                        
                            
                            # audio analysis
                            file_path = "audio_files/"+ split_name +".wav"
                            audio_format = "wav"

                            audio = AudioSegment.from_file(file_path , format = audio_format)
                            n = len(audio)
                            tme = (n/1000)
                            time_dec = ((n/1000)/60)
                            # time_min = (str(round(time_dec, 2)) + ' Min')
                            time_au = convert_to_preferred_format(tme)
                            print("Audio Length:",time_au)

                            pace_decimal = (total_words / time_dec)
                            pace = (str(round(pace_decimal , 2)))
                            print("Pace of Speech:",pace)

                            # volume analysis
                            print('Volume in dBFS:',audio.dBFS)
                            audio_vol = (str(round(audio.dBFS, 2)))
                            
                            if audio.dBFS < -60:
                                audio_vol = -100
                            
                            if audio.dBFS > -10:
                                vol = "loud"
                                print(vol)
                            elif audio.dBFS < -10 and audio.dBFS > -30:
                                vol = "Normal"
                                print(vol)
                            elif audio.dBFS < -30:
                                vol = "Low"
                                print(vol)

                            # pause counter
                            audio_pause = []
                            chunk_ar = []
                            arr_ps = []
                            audio_pause_arr = detect_silence(audio, min_silence_len=3200, silence_thresh=-40)
                            for chunks in audio_pause_arr:
                                chunk_ar = ([convert_to_preferred_format(chunk/1000) for chunk in chunks])
                                # print(convert_to_preferred_format(chunk_ar))
                                audio_pause.append(chunk_ar)
                            
                            for key, value in audio_pause:
                                # print(key)
                                # print(value)
                                arr_ps.append(key)
                            
                            if not chunk_ar:
                                print("Pause timimg array:", arr_ps)
                            else:
                                print("Pause timimg array bef-pop:", arr_ps)
                                if arr_ps[0] == ' 0:00':
                                    arr_ps.pop(0)
                                    # print('yes')
                                print("Pause timimg array pop:", arr_ps)
                            puse = len(arr_ps)
                            print("pause:", puse)

                            os.remove("audio_files/"+ split_name +".wav") 

                        except BaseException as e:
                            print(f"MoviePyError: {e}")
                            er_movie = er_movie + 1
                            print("Moviepy Error Detected:", er_movie)
                                           
                        
                        # video light analysis
                        face_casecade=cv2.CascadeClassifier('frontface_default.xml')
                        smile_cascade=cv2.CascadeClassifier('haarcascade_smile.xml')
                        cntr = 0
                        lft = 0
                        rght = 0
                        count_s = 0
                         
                        cap = cv2.VideoCapture(url)
                        gaze = GazeTracking()
                        fps = cap.get(cv2.CAP_PROP_FPS)
                        print(f"{fps} frames per second")
                        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
                        if total_frames > 0:
                            print(total_frames)
                            
                            
                            for ft in range(0, total_frames):
                                ret,frame = cap.read()
                                try:
                                    gaze.refresh(frame)
                                    new_frame = gaze.annotated_frame()
                                    if gaze.is_right():
                                        rght = rght + 1
                                    
                                    elif gaze.is_left():
                                        lft = lft + 1
                                        
                                    elif gaze.is_center():
                                        cntr = cntr + 1

                                except Exception as e:
                                    err_eye = err_eye + 1
                                    # print(f"Error during eye detection: {e}")

                                try:
                                    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)     
                                    face = face_casecade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5)    
                                    for (x,y,w,h) in face:
                                        cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)
                                        roi_gray = gray[y:y+h, x:x+w] 
                                        roi_img = frame[y:y+h, x:x+w]      
                                        smile = smile_cascade.detectMultiScale(roi_gray, scaleFactor= 1.6, minNeighbors=20)         
                                        for (x,y,w,h) in smile: 
                                            cv2.rectangle(roi_img,(x,y),(x+w,y+h),(0,0,255),2)
                                            count_s = count_s+1
                                            # c_ar.append(count)
                                
                                except Exception as e:
                                    err_smle = err_smle + 1
                                    # print(f"Error during smile detection: {e}")
                            
                            smile_count = (count_s)
                            
                            print("Right",rght)
                            print("Left",lft)
                            print("Center",cntr)
                            print("Smile",smile_count)
                            print("Error during eye detection:",err_eye )
                            print("Error during smile detection:",err_smle )
                            print("Error during audio detection:",err_audio )

                            # percentage calculation of eye tracking
                            
                            total_eye_percentage = (((cntr + lft + rght) / total_frames) * 100)
                            dis_total_eye_percentage = (str(round(total_eye_percentage, 2)))
                            print(dis_total_eye_percentage)
                            if(total_eye_percentage > 80):
                                eye_cap_note = "Good eye captured by the camera."
                                print(eye_cap_note)
                            elif(total_eye_percentage < 80 and total_eye_percentage > 20):
                                eye_cap_note = "Normal eye captured by the camera."
                                print(eye_cap_note)
                            elif(total_eye_percentage < 20):
                                eye_cap_note = "Eye not properly captured by the camera."
                                print(eye_cap_note)
                            
                            center_per_eye = ((cntr / total_frames) * 100)
                            left_per_eye = ((lft / total_frames) * 100)
                            right_per_eye = ((rght / total_frames) * 100)

                            per_eye_contact_center = (str(round(center_per_eye, 2)))
                            per_eye_contact_left = (str(round(left_per_eye, 2)))
                            per_eye_contact_right = (str(round(right_per_eye, 2)))
                            
                            print(per_eye_contact_center)
                            print(per_eye_contact_left)
                            print(per_eye_contact_right)
                            
                            eye_contact_behav = ""

                            if(center_per_eye > left_per_eye or right_per_eye):
                                eye_contact_behav = "Good eye contact [based on the Total Eye Capture]"
                                print(eye_contact_behav) 
                            elif(left_per_eye > center_per_eye or right_per_eye):
                                eye_contact_behav = "Leftside eye contact [based on the Total Eye Capture]"
                                print(eye_contact_behav)
                            elif(right_per_eye > center_per_eye or left_per_eye):
                                eye_contact_behav = "Rightside eye contact [based on the Total Eye Capture]"
                                print(eye_contact_behav)
                            

                            # percentage calculation of smiling

                            total_smile_percentage = (((smile_count) / total_frames) * 100)
                            dis_total_smile_percentage = (str(round(total_smile_percentage, 2)))
                            print(dis_total_smile_percentage)

                            

                            count = []
                            lght = ''
                            arr1 = 0
                            for fp in range(0, total_frames):
                                # ret,frame = cap.read()
                                hsvImage = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
                                h,s,v = cv2.split(hsvImage)
                                live_value = cv2.mean(v)
                                count.append(live_value[0])
                            
                            arr = np.array(count)
                            arr_decimal = np.mean(arr)
                            arr1 = round(arr_decimal, 2)
                            # print(arr1)
                            if arr1 > (150):
                                lght = "High Light Video"
                                # print("High Light Video")
                            elif arr1 < (150) and arr1 > (50):
                                lght = "Normal Light Video"
                                # print("Normal Light Video")
                            elif arr1 < (50):
                                lght = "Low Light Video"
                                # print("Low Light Video") 
                        
                        else:
                            print("Video Frames not detected.")
                        
                        
                        result_text = {"video_cc": reslt, "audio_length": time_au, "audio_volume_dBFS": audio_vol, "total_words_spoken": total_words, "pace_of_speech": pace, "audio_volume": vol, "pause": puse, "pause_timestamp": arr_ps, "video_light_value": arr1, "video_light": lght, "filler_word_count": new_filler, "power_word_count": new_total_power_count, "negative_word_count": ngtv_count, "um_word_count": um_count, "filler_word_timestamp": new_f_ar, "filler_count": filler_word_counts, "filler_phrases" :ph_filler_wrds, "filler_phrase_counter" :total_filler_words, "power_phrases" :ph_power_wrds, "power_phrase_counter" :total_power_words, "power_word_timestamp": new_p_ar, "power_count": power_word_counts, "negative_word_timestamp": new_n_ar, "negative_count": ngtv_word_counts, "um_word_timestamp": um_time_arr, "um_count": um_word_counts, "total_video_frames": total_frames, "eye_contact_leftside": lft, "eye_contact_rightside": rght, "eye_contact_center": cntr, "smiling_frames": smile_count, "total_eye_capture": dis_total_eye_percentage, "percentage_eye_contact_center": per_eye_contact_center, "percentage_eye_contact_left": per_eye_contact_left, "percentage_eye_contact_right": per_eye_contact_right, "eye_contact_behavior": eye_contact_behav, "total_smile_capture": dis_total_smile_percentage}
                        # dm_ar = []
                        # dm_ar.append(result_text)
                        
                        # print(dm_ar)
                        new_rsltxt = json.dumps(result_text)
                    
                    mycursor = mydb.cursor()

                    usr_id = str(user_id)
                    intrvw_id = str(interview_id)
                    qsn_id = str(question_id)

                    sql_search_Query = "SELECT * FROM mip_ai_generate_feedback_data_tbl WHERE user_id = '"+usr_id+"' AND interview_id = '"+intrvw_id+"'  AND question_id = '"+qsn_id+"' ORDER BY id DESC LIMIT 1"
                    mycursor.execute(sql_search_Query)

                    records = mycursor.fetchall()
                    # print(records)
                    if mycursor.rowcount > 0:
                        new_id = str(records[0][0])
                        print("Generate result id",new_id)
                        # upChksql = 'UPDATE mip_ai_generate_feedback_data_tbl SET content = "'+new_rsltxt+'" WHERE id = "'+new_id+'"'
                        delSql = "DELETE FROM mip_ai_generate_feedback_data_tbl WHERE id = '"+new_id+"'"
                        mycursor.execute(delSql)
                        print(mycursor.rowcount, "record deleted.")
                        
                        nw_sql = "INSERT INTO mip_ai_generate_feedback_data_tbl (user_id,interview_id,question_id,interview_type,content) VALUES (%s, %s, %s, %s, %s)"
                        nw_val = (user_id, interview_id, question_id, interview_type, new_rsltxt)
                        mycursor.execute(nw_sql, nw_val)
                        mydb.commit()
                        print(mycursor.rowcount, "record inserted.")
                    else:
                        sql = "INSERT INTO mip_ai_generate_feedback_data_tbl (user_id,interview_id,question_id,interview_type,content) VALUES (%s, %s, %s, %s, %s)"
                        val = (user_id, interview_id, question_id, interview_type, new_rsltxt)

                        mycursor.execute(sql, val)

                        mydb.commit()

                        print(mycursor.rowcount, "record inserted.")

                    # end process time
                    now_utc = datetime.now(timezone('America/Los_Angeles'))
                    end_time = now_utc.strftime("%Y-%m-%d %H:%M:%S") 
                    print(end_time)  
                    
                    str_time = str(time_au)

                    if err_audio > 0:
                        errMsg = (f"Audio error found.{err_audio}")
                        print(errMsg)
                        upErsql = "UPDATE mip_ai_feedback_queue_tbl SET status = '3', process_end_time = '"+end_time+"', duration = '"+str_time+"', exception = '"+errMsg+"' WHERE id = '"+result_db+"'"
                        cursor.execute(upErsql)
                        mydb.commit()
                        print(cursor.rowcount, "record(s) updated for audio")

                    if er_movie > 0:
                        errMsg = (f"Video error found.{er_movie}")
                        print(errMsg)
                        upErsql = "UPDATE mip_ai_feedback_queue_tbl SET status = '3', process_end_time = '"+end_time+"', duration = '"+str_time+"', exception = '"+errMsg+"' WHERE id = '"+result_db+"'"
                        cursor.execute(upErsql)
                        mydb.commit()
                        print(cursor.rowcount, "record(s) updated for Video")
                    
                    if err_eye > 0:
                        errMsg = (f"Eye-detection error found. {err_eye} frames")
                        upErsql = "UPDATE mip_ai_feedback_queue_tbl SET status = '3', process_end_time = '"+end_time+"', duration = '"+str_time+"', exception = '"+errMsg+"' WHERE id = '"+result_db+"'"
                        cursor.execute(upErsql)
                        mydb.commit()
                        print(cursor.rowcount, "record(s) updated")
                    
                    if err_smle > 0:
                        errMsg = (f"Smile-detection error found. {err_smle} frames")
                        upErsql = "UPDATE mip_ai_feedback_queue_tbl SET status = '3', process_end_time = '"+end_time+"', duration = '"+str_time+"', exception = '"+errMsg+"' WHERE id = '"+result_db+"'"
                        cursor.execute(upErsql)
                        mydb.commit()
                        print(cursor.rowcount, "record(s) updated")

                    if ((err_audio > 0 and err_eye > 0) or (err_eye > 0 and err_smle > 0) or (err_audio > 0 and err_smle > 0) or (err_audio > 0 and err_eye > 0 and err_smle > 0)):
                        errMsg = ("Multiple errors found. Please check the video")
                        upErsql = "UPDATE mip_ai_feedback_queue_tbl SET status = '3', process_end_time = '"+end_time+"', duration = '"+str_time+"', exception = '"+errMsg+"' WHERE id = '"+result_db+"'"
                        cursor.execute(upErsql)
                        mydb.commit()
                        print(cursor.rowcount, "record(s) updated")

                    # delsql = "DELETE FROM mip_ai_feedback_queue_tbl WHERE id='"+result_db+"'"
                    upsql = "UPDATE mip_ai_feedback_queue_tbl SET status = '3', process_end_time = '"+end_time+"', duration = '"+str_time+"' WHERE id = '"+result_db+"'"
                    cursor.execute(upsql)
                    mydb.commit()
                    print(cursor.rowcount, "record(s) updated")
                    int_id = str(interview_id)
                    int_ty = str(interview_type)

                    sql_check_Query = "SELECT * FROM mip_ai_feedback_queue_tbl WHERE status IN ('0','1') AND interview_id = '"+int_id+"' AND interview_type = '"+interview_type+"' ORDER BY created_at"
                    # sql_check_Query = "SELECT * FROM mip_ai_feedback_queue_tbl WHERE interview_id='"+int_id+"' ORDER BY created_at"
                    
                    cursor.execute(sql_check_Query)
                    records = cursor.fetchall()
                    print("remaining rows in table: ", cursor.rowcount)
                    if cursor.rowcount == 0:
                        if interview_type == '1':
                            sql_reupdate_Query = "UPDATE mip_interview_tbl SET ai_feedback = '2' WHERE id = '"+int_id+"'"
                            cursor.execute(sql_reupdate_Query)
                            mydb.commit()
                            print(cursor.rowcount, "record(s) affected")
                        else:
                            sql_reupdate_Query = "UPDATE mip_giving_custom_interview_tbl SET ai_feedback = '2' WHERE id = '"+int_id+"'"
                            cursor.execute(sql_reupdate_Query)
                            mydb.commit()
                            print(cursor.rowcount, "record(s) affected")
                        
                        url = 'https://myinterviewpractice.com/ajax/api/ai_feedbak_notify.php'
                        payload = 'interview_id='+int_id+'&type='+int_ty
                        headers = { 
                        'Content-Type': 'application/x-www-form-urlencoded', 
                        } 
                        response = requests.request("POST", url, headers=headers, data=payload) 
                        print(response.text)
                        
                        # print(response.json())

                    return jsonify(result_text)
                except Exception as e:
                    # Catch any other exceptions not handled above
                    ex_err = (f"An error occurred: {e}")
                    gt_err = ("Error: An unexpected error occurred.")
                    print(ex_err)
                    result_errtext = {"error": 'Video is not loaded properly.'}
                    new_errsltxt = json.dumps(result_errtext)
                    upexsql = "UPDATE mip_ai_feedback_queue_tbl SET status = '2', exception = '"+gt_err+"', process_start_time = NULL WHERE id = '"+result_db+"'"
                    cursor.execute(upexsql)
                    mydb.commit()
                    print(cursor.rowcount, "record(s) updated")
                    
                    
                    usr_id = str(user_id)
                    intrvw_id = str(interview_id)
                    qsn_id = str(question_id)

                    sql_search_Query = "SELECT * FROM mip_ai_generate_feedback_data_tbl WHERE user_id = '"+usr_id+"' AND interview_id = '"+intrvw_id+"'  AND question_id = '"+qsn_id+"' ORDER BY id DESC LIMIT 1"
                    cursor.execute(sql_search_Query)

                    records = cursor.fetchall()
                    # print(records)
                    if cursor.rowcount > 0:
                        new_id = str(records[0][0])
                        print("Generate result id",new_id)
                        # upChksql = 'UPDATE mip_ai_generate_feedback_data_tbl SET content = "'+new_rsltxt+'" WHERE id = "'+new_id+'"'
                        delSql = "DELETE FROM mip_ai_generate_feedback_data_tbl WHERE id = '"+new_id+"'"
                        cursor.execute(delSql)
                        print(cursor.rowcount, "record deleted.")
                        
                        ersql = "INSERT INTO mip_ai_generate_feedback_data_tbl (user_id,interview_id,question_id,interview_type,content) VALUES (%s, %s, %s, %s, %s)"
                        erval = (user_id, interview_id, question_id, interview_type, new_errsltxt)
                        cursor.execute(ersql, erval)
                        mydb.commit()
                        print(cursor.rowcount, "record inserted.")
                    else:
                        er_nwsql = "INSERT INTO mip_ai_generate_feedback_data_tbl (user_id,interview_id,question_id,interview_type,content) VALUES (%s, %s, %s, %s, %s)"
                        er_nwval = (user_id, interview_id, question_id, interview_type, new_errsltxt)
                        cursor.execute(er_nwsql, er_nwval)
                        mydb.commit()
                        print(cursor.rowcount, "record inserted.")

                    int_id = str(interview_id)
                    int_ty = str(interview_type)

                    sql_check_Query = "SELECT * FROM mip_ai_feedback_queue_tbl WHERE status IN ('0','1') AND interview_id = '"+int_id+"' AND interview_type = '"+interview_type+"' ORDER BY created_at"
                    # sql_check_Query = "SELECT * FROM mip_ai_feedback_queue_tbl WHERE interview_id='"+int_id+"' ORDER BY created_at"
                    
                    cursor.execute(sql_check_Query)
                    records = cursor.fetchall()
                    print("remaining rows in table: ", cursor.rowcount)
                    if cursor.rowcount == 0:
                        if interview_type == '1':
                            sql_reupdate_Query = "UPDATE mip_interview_tbl SET ai_feedback = '2' WHERE id = '"+int_id+"'"
                            cursor.execute(sql_reupdate_Query)
                            mydb.commit()
                            print(cursor.rowcount, "record(s) affected")
                        else:
                            sql_reupdate_Query = "UPDATE mip_giving_custom_interview_tbl SET ai_feedback = '2' WHERE id = '"+int_id+"'"
                            cursor.execute(sql_reupdate_Query)
                            mydb.commit()
                            print(cursor.rowcount, "record(s) affected")
                        
                        url = 'https://staging.myinterviewpractice.com/ajax/api/ai_feedbak_notify.php'
                        payload = 'interview_id='+int_id+'&type='+int_ty
                        headers = { 
                        'Content-Type': 'application/x-www-form-urlencoded', 
                        } 
                        response = requests.request("POST", url, headers=headers, data=payload) 
                        print(response.text)
            else:
                err = "No record found"
                print(err)
                return (err)
        else:
            err1 = "Queue is in progress"
            print(err1)
            time_data = 0
            for row in records:
                time_data = row[10]
                result_db = row[0] 
            new_tme = (str(time_data))
            print('new time:',new_tme)
            now_utc1 = datetime.now(timezone('America/Los_Angeles'))
            cur_time = now_utc1.strftime("%Y-%m-%d %H:%M:%S") 
            print("current time:", cur_time)        
            spend_time = ((datetime.strptime(cur_time, "%Y-%m-%d %H:%M:%S")) - (datetime.strptime(new_tme, "%Y-%m-%d %H:%M:%S")))
            hours = spend_time.total_seconds() // 3600
            minutes = (spend_time.total_seconds() % 3600) // 60
            seconds = spend_time.total_seconds() % 60
            print(f"The difference is {hours} hours, {minutes} minutes, and {seconds} seconds.")
            if hours >= 2:
                print("Processing time is exceed 2 hours.")
                for nrow in records:
                    video_name = nrow[1]
                    user_id = nrow[2]
                    interview_id = nrow[3]
                    question_id = nrow[4]
                    interview_type = nrow[5]
                    data_process = nrow[7]
                    tries = nrow[8]
                new_resultid = round(time.time() * 1000)
                now_utc = datetime.now(timezone('America/Los_Angeles'))
                create_time = now_utc.strftime("%Y-%m-%d %H:%M:%S")
                created_at = create_time
                mycursor = mydb.cursor()
                inssql = "INSERT INTO mip_ai_feedback_queue_tbl (id,video_name,user_id,interview_id,question_id,interview_type,status,data_process,tries,created_at,process_start_time,process_end_time,duration,exception) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
                val = (new_resultid, video_name, user_id, interview_id, question_id, interview_type, '0', data_process, tries, created_at, None, None, None, None)

                mycursor.execute(inssql, val)
                mydb.commit()
                print(mycursor.rowcount, "record inserted.")
                tmeout_err = "Processing time is exceed 2 hours"
                uptmesql = "UPDATE mip_ai_feedback_queue_tbl SET status = '2', exception = '"+tmeout_err+"' WHERE id = '"+result_db+"'"
                cursor.execute(uptmesql)
                mydb.commit()
                print(cursor.rowcount, "record(s) updated")
            else:
                print("Program is processing...")
            return (err1)
    except mysql.connector.Error as e:
        print("Error reading data from MySQL table", e)

if __name__ == '__main__':
    context = ('/etc/letsencrypt/live/ai-feedback.myinterviewpractice.com/fullchain.pem', '/etc/letsencrypt/live/ai-feedback.myinterviewpractice.com/privkey.pem')
    # Set the hostname and port number
    hostname = "0.0.0.0"
    port = 9001
    
    # Start the Flask app
    # app.run(debug=True, port=port)  
    # app.run(host=hostname, port=port, ssl_context='adhoc')
    app.run(host=hostname, port=port, ssl_context=context, threaded=True, debug=False)