import os
import copy
import json
import time
import shutil
import hashlib
import base64

import KCADBProcessorUtilities as KCAProc
import KCALLMTrace as KCATrace
import KCALLMUtilities as KCAUtil
import KCALLMCore


def getBestSolutions(iSols, jSportDB):

    # Init
    fsols = []

    # Foodlist must be an array
    actList = iSols
    if not isinstance(actList, list):
        actList = [iSols]

    levels = getLevelOfActivity()
    for aa in actList:

        act = KCAUtil.ignorePrefix("activity:", aa)

        fsol = False
        nameLLM = ""
        try:
            nameLLM = act["name"].lower()
        except:
            print("***************************")
            print("*    Wrong JSON format    *")
            print("***************************")
            print("Object dump:")
            print(act)
            return fsols
        
        for js in jSportDB:
            nameDB = js["name"]["fr"].lower()
            if nameLLM == nameDB:
                
                sol = {}

                # Trigram & duration
                sol["trigram"] = js["trigram"]

                # Duration
                duration = 0
                try:
                    duration = act["duration"]
                except:
                    pass
                sol["duration"] = duration

                # Event
                eventTime = ""
                try:
                    eventTime = act["event"]
                except:
                    pass
                sol["event"] = eventTime

                # intensity
                intensity = "unknown"
                try:
                    intensity = act["intensity"]

                    # Hallucination
                    intensity = removeIntensityArtefact(intensity)
                except:
                    pass

                # New solution
                if intensity == "unknown":
                    medVal = int(len(js["levels"])/2)
                    sol["level"] = js['levels'][medVal]['code']
                else:
                    nbLevelSport = len(js["levels"]) - 1
                    speechLevel = float(levels.index(intensity)) / float(len(levels) - 1) # we remove "unknown"
                    idx = int(float(nbLevelSport - 1) * speechLevel)
                    sol["level"] = js['levels'][idx]['code']

                # Add solution
                fsols.append(sol)
                fsol = True
                
                break
            
        if fsol == False:
            KCATrace.TRACE("Warning: no activity found for '" + nameLLM + "'")
            

    return fsols


def removeIntensityArtefact(intensity):
    
    oIntensity = intensity
    if oIntensity.find('Level') != -1:
        oIntensity = oIntensity.replace('Level', '')
    if oIntensity == 'veryIntense':
        oIntensity = 'very intense'
    
    return oIntensity


def getLevelOfActivity():

    return ["low", "moderate", "high", "intense", "very intense"]


def getDumpDirectoryPath():

    dirRec = os.path.join(os.getcwd(), "__dumps__")

    return dirRec


def getDumpDirectoryPathByModel(mdl):

    dirRec = getDumpDirectoryPath()
    model = KCALLMCore.getModelNickName(mdl)
    dirRes = os.path.join(dirRec, model)
    if not os.path.exists(dirRes):
        os.mkdir(dirRes)

    return dirRes


def cleanDumps():

    dirRec = getDumpDirectoryPath()
    if os.path.isdir(dirRec):
        shutil.rmtree(dirRec)
    os.mkdir(dirRec)

    return


def getHexKey(ss):

    hash_object = hashlib.sha256()
    hash_object.update(ss.encode())
    hexKey = hash_object.hexdigest()

    return hexKey[0:16]



def extractSummary(jres):

    dumpResult = {}
    dumpResult['prompt'] = jres['prompt']
    dumpResult['model'] = jres['model']
    dumpResult['nutritionCount'] = len(jres['solutions']['nutrition'])
    dumpResult['activityCount'] = len(jres['solutions']['activity'])
    dumpResult['profileCount'] = 0
    
    return dumpResult


def recordResult(jres, imagePath):

    mdl = jres['model']
    dirRec = getDumpDirectoryPathByModel(mdl)
    if not os.path.isdir(dirRec):
        os.mkdir(dirRec)

    # Convert JSON in string
    dumpResult = extractSummary(jres)
    prompt = dumpResult['prompt']
    if prompt == '':
        prompt = imagePath
    hexKey = getHexKey(prompt)    
    filePath = os.path.join(dirRec, hexKey + ".json")

    # Save
    sdump = json.dumps(jres)
    with open(filePath, 'w') as file:
        file.write(sdump)
        file.close()
        
    return dumpResult



def compareResults(jres1, jres2):

    rc = 0
    msg = ''

    # Nutrition hit
    nbNut1 = len(jres1['solutions']['nutrition'])
    nbNut2 = len(jres2['solutions']['nutrition'])
    if (nbNut1 != nbNut2):
        rc = 2000
        msg = "Not the same number of nutrition hits"

    # Activity hit
    nbAct1 = len(jres1['solutions']['activity'])
    nbAct2 = len(jres2['solutions']['activity'])
    if (nbAct1 != nbAct2):
        rc = 3000
        msg = "Not the same number of activity hits"

    return rc, msg

def alreadyExists(jres, image64):

    mdl = KCALLMCore.getModelFromFamily("")
    dirRec = getDumpDirectoryPathByModel(mdl)
    if not os.path.isdir(dirRec):
        return False

    # Compute key
    prompt = jres['prompt']

    if prompt != "":

        hexKey = getHexKey(prompt)

        # Check file
        filePath = os.path.join(dirRec, hexKey + ".json")
        if os.path.exists(filePath):
            return True
    
    else:

        hexKey = getHexKey(image64)
        filePath = os.path.join(dirRec, hexKey)
        if os.path.exists(filePath + ".png"):
            return True
        elif os.path.exists(filePath + ".jpeg"):
            return True
        elif os.path.exists(filePath + ".jpg"):
            return True

    return False
    

def checkResult(jres):

    jrc = {"rc":0, "msg": ""}

    mdl = jres['model']
    dirRec = getDumpDirectoryPathByModel(mdl)
    if not os.path.isdir(dirRec):
        jrc["rc"] = 1000
        jrc["msg"] = "No dump directory"
        return jrc

    # Convert JSON in string
    prompt = jres['prompt']
    hexKey = getHexKey(prompt)

    # Read the dump
    filePath = os.path.join(dirRec, hexKey + ".json")
    if not os.path.exists(filePath):
        print("Dump for prompt '" + prompt + "' does not exist, it will be created")
        recordResult(jres, "")
        return jrc

    # Compare
    with open(filePath, 'r') as file:
        
        jresRef = json.load(file)
        file.close()

        rc, msg = compareResults(jres, jresRef)
        jrc['rc'] = rc
        jrc['msg'] = msg
        
    return jrc

