import mysql.connector
from datetime import datetime
import pymongo
import pytz



'''
This module queries the MySQL replication status
Updates the MongoDB collection with any value differences between each iteration
'''



def slaveStatus(
        CURSOR: mysql.connector,
        env: dict
    ) -> dict:
    '''
    Performs the slave status MySQL query and returns a dictionary
    '''

    # Execute MySQL query
    query = (
        "show slave status"
    )
    CURSOR.execute(query)
    myresult = CURSOR.fetchall()
    myresult = myresult[0]

    # Get the local time and make it timezone aware
    local_time = datetime.now()
    local_time = local_time.replace(tzinfo=pytz.timezone(env.timezone))
    # Convert the result to a dictionary
    result = {
        "datetime": local_time,
        "Slave_IO_State": myresult[0],
        "Master_Host": myresult[1],
        "Master_User": myresult[2],
        "Master_Port": myresult[3],
        "Connect_Retry": myresult[4],
        "Master_Log_File": myresult[5],
        "Read_Master_Log_Pos": myresult[6],
        "Relay_Log_File": myresult[7],
        "Relay_Log_Pos": myresult[8],
        "Relay_Master_Log_File": myresult[9],
        "Slave_IO_Running": myresult[10],
        "Slave_SQL_Running" : myresult[11],
        "Replicate_Do_DB" : myresult[12],
        "Replicate_Ignore_DB" : myresult[13],
        "Replicate_Do_Table" : myresult[14],
        "Replicate_Ignore_Table" : myresult[15],
        "Replicate_Wild_Do_Table" : myresult[16],
        "Replicate_Wild_Ignore_Table" : myresult[17],
        "Last_Errno" : myresult[18],
        "Last_Error" : myresult[19],
        "Skip_Counter" : myresult[20],
        "Exec_Master_Log_Pos" : myresult[21],
        "Relay_Log_Space" : myresult[22],
        "Until_Condition" : myresult[23],
        "Until_Log_File": myresult[24],
        "Until_Log_Pos": myresult[25],
        "Master_SSL_Allowed": myresult[26],
        "Master_SSL_CA_File": myresult[27],
        "Master_SSL_CA_Path": myresult[28],
        "Master_SSL_Cert": myresult[29],
        "Master_SSL_Cipher": myresult[30],
        "Master_SSL_Key": myresult[31],
        "Seconds_Behind_Master": myresult[32],
        "Master_SSL_Verify_Server_Cert": myresult[33],
        "Last_IO_Errno": myresult[34],
        "Last_IO_Error": myresult[35],
        "Last_SQL_Errno": myresult[36],
        "Last_SQL_Error": myresult[37],
        "Replicate_Ignore_Server_Ids": myresult[38],
        "Master_Server_Id": myresult[39],
        "Master_UUID": myresult[40],
        "Master_Info_File": myresult[41],
        "SQL_Delay": myresult[42],
        "SQL_Remaining_Delay": myresult[43],
        "Slave_SQL_Running_State": myresult[44],
        "Master_Retry_Count": myresult[45],
        "Master_Bind": myresult[46],
        "Last_IO_Error_Timestamp": myresult[47],
        "Last_SQL_Error_Timestamp": myresult[48],
        "Master_SSL_Crl": myresult[49],
        "Master_SSL_Crlpath": myresult[50],
        "Retrieved_Gtid_Set": myresult[51],
        "Executed_Gtid_Set": myresult[52],
        "Auto_Position": myresult[53],
        "Replicate_Rewrite_DB": myresult[54],
        "Channel_Name": myresult[55],
        "Master_TLS_Version": myresult[56],
    }

    return(result)


def updateLive(
        DB: pymongo.MongoClient,
        data: dict
    )-> None:
    ''' 
    Updates the live information MongoDB docuement
    '''
    # Insert the live data in to the dictionary
    data['type'] = 'live'

    DB['tetra_replication'].find_one_and_update(
        {
            'type' : 'live'
        },
        {
            '$set': data
        },
        upsert=True
    )


def updateDB(
        DB: pymongo.MongoClient,
        data: dict
    ) -> None:
    '''
     Inserts dictionary in to the MongoDB collection
    '''
    # Inserts the document for historical information
    DB['tetra_replication'].insert_one(
        data
    )


def getLast(
        DB: pymongo.MongoClient
    ) -> tuple[dict, dict]:
    '''
    Retrieves the previous and first status for comparison
    Returns the difference only
    '''
    # Get the first ever record
    first = DB['tetra_replication'].find({'type' :{'$ne':'live'}}, {'_id': False}).sort("datetime", pymongo.ASCENDING).limit(1)
    try:
        first = list(first)[0]
    except IndexError:
        first = {}

    # Get the most recent record
    last = DB['tetra_replication'].find({'type' :{'$ne':'live'}}, {'_id': False}).sort("datetime", pymongo.DESCENDING).limit(1)
    try:
        last = list(last)[0]
    except IndexError:
        last = {}

    return(first, last)


def getDifference(
        status: dict,
        first: dict,
        last: dict
    ) -> dict:
    '''
    Compares two dictionaries and returns the difference
    '''

    # Most recent datapoint
    status = set(status.items())
    # First datapoint
    first = set(first.items())
    # Previous datapoint
    last = set(last.items())
    
    # Get the difference from the first and most recent data points
    difference = status - first
    # Then get the difference between the remaining data points and the previous data point
    difference = difference - last
    # Conert back to a dictionary
    difference = dict(difference)

    return(difference)


def getStatus(
        CURSOR: mysql.connector,
        DB: pymongo.MongoClient,
        env: dict
    ) -> None:
    '''
    Gets the current MySQL slave replication status
    Inserts a new document in to MongoDB with a datatime stamp
    '''

    status = slaveStatus(CURSOR, env)
    updateLive(DB, status)
    first, last = getLast(DB)
    difference = getDifference(status, first, last)
    updateDB(DB, difference)
import mysql.connector
from datetime import datetime
import pymongo
import pytz



'''
This module queries the MySQL replication status
Updates the MongoDB collection with any value differences between each iteration
'''



def slaveStatus(
        CURSOR: mysql.connector,
        env: dict
    ) -> dict:
    '''
    Performs the slave status MySQL query and returns a dictionary
    '''

    # Execute MySQL query
    query = (
        "show slave status"
    )
    CURSOR.execute(query)
    myresult = CURSOR.fetchall()
    myresult = myresult[0]

    # Get the local time and make it timezone aware
    local_time = datetime.now()
    local_time = local_time.replace(tzinfo=pytz.timezone(env.timezone))
    # Convert the result to a dictionary
    result = {
        "datetime": local_time,
        "Slave_IO_State": myresult[0],
        "Master_Host": myresult[1],
        "Master_User": myresult[2],
        "Master_Port": myresult[3],
        "Connect_Retry": myresult[4],
        "Master_Log_File": myresult[5],
        "Read_Master_Log_Pos": myresult[6],
        "Relay_Log_File": myresult[7],
        "Relay_Log_Pos": myresult[8],
        "Relay_Master_Log_File": myresult[9],
        "Slave_IO_Running": myresult[10],
        "Slave_SQL_Running" : myresult[11],
        "Replicate_Do_DB" : myresult[12],
        "Replicate_Ignore_DB" : myresult[13],
        "Replicate_Do_Table" : myresult[14],
        "Replicate_Ignore_Table" : myresult[15],
        "Replicate_Wild_Do_Table" : myresult[16],
        "Replicate_Wild_Ignore_Table" : myresult[17],
        "Last_Errno" : myresult[18],
        "Last_Error" : myresult[19],
        "Skip_Counter" : myresult[20],
        "Exec_Master_Log_Pos" : myresult[21],
        "Relay_Log_Space" : myresult[22],
        "Until_Condition" : myresult[23],
        "Until_Log_File": myresult[24],
        "Until_Log_Pos": myresult[25],
        "Master_SSL_Allowed": myresult[26],
        "Master_SSL_CA_File": myresult[27],
        "Master_SSL_CA_Path": myresult[28],
        "Master_SSL_Cert": myresult[29],
        "Master_SSL_Cipher": myresult[30],
        "Master_SSL_Key": myresult[31],
        "Seconds_Behind_Master": myresult[32],
        "Master_SSL_Verify_Server_Cert": myresult[33],
        "Last_IO_Errno": myresult[34],
        "Last_IO_Error": myresult[35],
        "Last_SQL_Errno": myresult[36],
        "Last_SQL_Error": myresult[37],
        "Replicate_Ignore_Server_Ids": myresult[38],
        "Master_Server_Id": myresult[39],
        "Master_UUID": myresult[40],
        "Master_Info_File": myresult[41],
        "SQL_Delay": myresult[42],
        "SQL_Remaining_Delay": myresult[43],
        "Slave_SQL_Running_State": myresult[44],
        "Master_Retry_Count": myresult[45],
        "Master_Bind": myresult[46],
        "Last_IO_Error_Timestamp": myresult[47],
        "Last_SQL_Error_Timestamp": myresult[48],
        "Master_SSL_Crl": myresult[49],
        "Master_SSL_Crlpath": myresult[50],
        "Retrieved_Gtid_Set": myresult[51],
        "Executed_Gtid_Set": myresult[52],
        "Auto_Position": myresult[53],
        "Replicate_Rewrite_DB": myresult[54],
        "Channel_Name": myresult[55],
        "Master_TLS_Version": myresult[56],
    }

    return(result)


def updateLive(
        DB: pymongo.MongoClient,
        data: dict
    )-> None:
    ''' 
    Updates the live information MongoDB docuement
    '''
    # Insert the live data in to the dictionary
    data['type'] = 'live'

    DB['tetra_replication'].find_one_and_update(
        {
            'type' : 'live'
        },
        {
            '$set': data
        },
        upsert=True
    )


def updateDB(
        DB: pymongo.MongoClient,
        data: dict
    ) -> None:
    '''
     Inserts dictionary in to the MongoDB collection
    '''
    # Inserts the document for historical information
    DB['tetra_replication'].insert_one(
        data
    )


def getLast(
        DB: pymongo.MongoClient
    ) -> tuple[dict, dict]:
    '''
    Retrieves the previous and first status for comparison
    Returns the difference only
    '''
    # Get the first ever record
    first = DB['tetra_replication'].find({'type' :{'$ne':'live'}}, {'_id': False}).sort("datetime", pymongo.ASCENDING).limit(1)
    try:
        first = list(first)[0]
    except IndexError:
        first = {}

    # Get the most recent record
    last = DB['tetra_replication'].find({'type' :{'$ne':'live'}}, {'_id': False}).sort("datetime", pymongo.DESCENDING).limit(1)
    try:
        last = list(last)[0]
    except IndexError:
        last = {}

    return(first, last)


def getDifference(
        status: dict,
        first: dict,
        last: dict
    ) -> dict:
    '''
    Compares two dictionaries and returns the difference
    '''

    # Most recent datapoint
    status = set(status.items())
    # First datapoint
    first = set(first.items())
    # Previous datapoint
    last = set(last.items())
    
    # Get the difference from the first and most recent data points
    difference = status - first
    # Then get the difference between the remaining data points and the previous data point
    difference = difference - last
    # Conert back to a dictionary
    difference = dict(difference)

    return(difference)


def getStatus(
        CURSOR: mysql.connector,
        DB: pymongo.MongoClient,
        env: dict
    ) -> None:
    '''
    Gets the current MySQL slave replication status
    Inserts a new document in to MongoDB with a datatime stamp
    '''

    status = slaveStatus(CURSOR, env)
    updateLive(DB, status)
    first, last = getLast(DB)
    difference = getDifference(status, first, last)
    updateDB(DB, difference)
This module queries the MySQL replication status Updates the MongoDB collection with any value differences between each iteration Performs the slave status MySQL query and returns a dictionary # Execute MySQL query # Get the local time and make it timezone aware # Convert the result to a dictionary Updates the live information MongoDB docuement # Insert the live data in to the dictionary Inserts dictionary in to the MongoDB collection # Inserts the document for historical information Retrieves the previous and first status for comparison     Returns the difference only # Get the first ever record # Get the most recent record Compares two dictionaries and returns the difference # Most recent datapoint # First datapoint # Previous datapoint # Get the difference from the first and most recent data points # Then get the difference between the remaining data points and the previous data point # Conert back to a dictionary Gets the current MySQL slave replication status     Inserts a new document in to MongoDB with a datatime stamp