import os
import sys
import importlib.util
import pathlib
import shutil
import re
'''
This script searches for all 'tests/' directories and executes all tests 
by cd'ing into the dir and executing unittest discover.
It additionally installs all dependencies from a '../requirements.txt' via pip.
Use command line argument '-w' to run on windows.
'''

PY = sys.argv[2] if (len(sys.argv) > 1 and sys.argv[1] == '-py') else 'python3.7' # use -py to use your own python command
ROOT = pathlib.Path(__file__).parent.parent.absolute()
REPORTS = ROOT / 'reports'
TESTS_FOLDER_NAME = os.path.normpath("/tests")

print("Creating VENV")
os.system(f"{PY} -m venv venv")

PY = f"~/smart/venv/bin/{PY}"

print("\nSearching for tests at the path: "+ str(ROOT))

count = 0
resultCodeList = []
microservice_coverage_paths_set = set()
for (dirname, dirs, files) in os.walk(ROOT):

    #I assume all the tests are placed in a folder named "tests"
    if (TESTS_FOLDER_NAME in str(dirname)) \
        and 'src' in str(dirname) \
        and not(f"{TESTS_FOLDER_NAME}{os.path.normpath('/')}" in str(dirname)) \
        and not("venv" in str(dirname)) \
        and not("Lib" in str(dirname)):
        try:
            print(f"Executing tests in {dirname}")
            os.chdir(os.path.normpath(dirname))
            # TODO do this during docker image setup
            exit_val = os.system(f"{PY} -m pip install -r ../requirements.txt") # install pip dependencies
            #resultCodeList.append(exit_val)
            #exit_val = os.system(f"{PY} -m unittest discover") # execute the tests
            exit_val = os.system(f"{PY} -m coverage run --append --omit=*/site-packages*,*/dist-packages* -m unittest discover") #TEST CODE COVERAGE
            microservice_coverage_paths_set.add(os.path.normpath(dirname))
            
            resultCodeList.append(exit_val) #once per folder  i.e if 3 tests are in a folder and crash, there will be just one exit val
        except Exception as e:
            print(e)
            continue
        try:
            cur_dir = pathlib.Path(os.path.normpath(dirname)).parent.absolute()
            filename_regular_expresion = re.compile('(test_.*)|(TEST_.*)')
            

            for filename in os.listdir(cur_dir):
                if filename_regular_expresion.match(filename): 
                    #gets here only if there is a test file which matches the regular expression in the app folder,
                    
                    #cur_dir = os.path(dirname).parent()
                    os.chdir(cur_dir)
                    print(f"Executing coverage test in {cur_dir}")
                    exit_val = os.system(f"{PY} -m coverage run --append --omit=*/site-packages* -m unittest discover")
                    microservice_coverage_paths_set.add(os.path.normpath(cur_dir))

        except Exception as e:
            print(e)
            continue
        


#CHANGE FOLDER TO REPORTS, in order to combine the coverage
try:
    if not os.path.exists(REPORTS):
        os.makedirs(REPORTS) 
except:
    pass


try: 
    os.chdir(REPORTS)
    target = REPORTS
    target = os.path.normpath( str(target) + f'/.coverage' )
    os.remove(target) #Try to Remove old coverage file, if exists
except Exception as e:
    pass

print("Combinging coverages")
counter = 0
for path in microservice_coverage_paths_set:
    try:
        path += '/.coverage'
        original = os.path.normpath( path )
        target = REPORTS
        target = os.path.normpath( str(target) + f'/.coverage.{counter}' )
        counter += 1

        shutil.copyfile(original,target) #copy new generated coverage files
        os.remove(original)
    except Exception as e:
        print(e)
        continue
try:
    coverage_xml_path = os.path.normpath( str(REPORTS) + '/coverage.xml')
    os.remove(coverage_xml_path)

    #coverage_html_path = os.path.normpath( str(REPORTS) + '/htmlcov' )
    #os.rmdir(coverage_html_path)
except Exception as e:
    print(e)


print("Generating Combined report")
os.system(f"{PY} -m coverage combine")
os.system(f"{PY} -m coverage xml")
os.system(f"{PY} -m coverage html") #if you want to generate the html as well

firstError = -1
i = 0
while i < len(resultCodeList):
    if resultCodeList[i] != 0:
        # print("\nA test failed with code: "+ str(resultCodeList[i]))
        if (firstError < 0):
            firstError = i
    i += 1

if(firstError<0): #no errors found
    sys.exit(0)
else:
    sys.exit(1) #return code>0

