import os
import json

from actions_logging.app_logging import logger
from common.common import run_command
from github.env import get_required_env_var, exit_on_error_and_write_summary
from lambdas.constants import DEFAULT_TEST_COVERAGE_VALUE

SVC_NAME = 'SVC_NAME'
DOMAIN_REPO = 'DOMAIN_REPO'
COVERAGE_GATE = 'COVERAGE_GATE'
COVERAGE_SUMMARY_FILE_DIR = ".coverage"
COVERAGE_SUMMARY_FILE_NAME = "coverage-summary.json"
WILL_FAIL = 'WILL_FAIL'
LAMBDA_LIST_FILE = "./lambda_names.env"


def check_coverage_summary_on_lambda_dir(coverage_summary_file, lambda_name = None,
                                         coverage_gate = None, will_fail = False):
    if not os.path.isfile(coverage_summary_file):
        raise FileNotFoundError(f'Coverage summary not found for {lambda_name}: {coverage_summary_file}')

    with open(coverage_summary_file) as f:
        coverage_summary = json.load(f)
    total_lines_pct = coverage_summary.get('total', {}).get('lines', {}).get('pct')

    if total_lines_pct is None:
        raise ValueError(f'Failed to retrieve coverage percentage for {lambda_name}')

    coverage_gate = int(coverage_gate) if coverage_gate and type(coverage_gate) == int else 1
    logger.info(f'Coverage gate for {lambda_name}: {coverage_gate}%')

    if total_lines_pct < coverage_gate:
        logger.info_red_bg(f'Coverage for {lambda_name} ({total_lines_pct}%) below threshold ({coverage_gate}%).')
        if will_fail:
            raise Exception(f"WILL_FAIL set to {will_fail}, exiting..")
    else:
        logger.info_green(f'Coverage for {lambda_name} ({total_lines_pct}%) meets or exceeds threshold ({coverage_gate}%).')


def main():
    error_message = ''
    try:
        lambda_name = os.getenv(SVC_NAME)
        is_domain_repo = os.getenv(DOMAIN_REPO, 'false').lower() == 'true'
        will_fail = os.getenv(WILL_FAIL, 'false').lower() == 'true'
        coverage_gate = os.getenv(COVERAGE_GATE, DEFAULT_TEST_COVERAGE_VALUE)

        if lambda_name:
            error_message = f'Tests failed for {lambda_name}'
            coverage_summary_file = os.path.join(COVERAGE_SUMMARY_FILE_DIR, lambda_name, COVERAGE_SUMMARY_FILE_NAME)

            logger.info(f'Running tests for single {lambda_name} lambda...')
            run_command(f'export NODE_OPTIONS=--max-old-space-size=4096; npm run test:lambdas-coverage "{lambda_name}"')
            logger.info(f'Checking coverage reports for single {lambda_name} lambda...')
            check_coverage_summary_on_lambda_dir(coverage_summary_file, lambda_name, coverage_gate, will_fail)
        elif is_domain_repo:
            error_message = 'Tests failed for Lambdas on Domain Repository'

            logger.info('Running tests for all Lambdas on Domain Repository...')
            run_command('npm run test:lambdas-coverage')
            with open(LAMBDA_LIST_FILE, 'r') as f:
                lambda_list = f.read().splitlines()
            if os.path.exists(LAMBDA_LIST_FILE):
                os.remove(LAMBDA_LIST_FILE)

            logger.info(f"Checking coverage reports for these lambdas: {', '.join(lambda_list)}")
            for name in lambda_list:
                coverage_summary_file = os.path.join(COVERAGE_SUMMARY_FILE_DIR, name, COVERAGE_SUMMARY_FILE_NAME)
                print(f"Checking coverage reports for {name} lambda...")
                check_coverage_summary_on_lambda_dir(coverage_summary_file, lambda_name, coverage_gate, will_fail)
        else:
            error_message = 'Tests failed for lambda on standard repository'
            coverage_summary_file = os.path.join(COVERAGE_SUMMARY_FILE_DIR, COVERAGE_SUMMARY_FILE_NAME)

            logger.info('Running tests for lambda on standard repo (default case)...')
            run_command('npm run test:lambdas-coverage')
            check_coverage_summary_on_lambda_dir(coverage_summary_file, None, coverage_gate, will_fail)
    except (FileNotFoundError, ValueError) as e:
        exit_on_error_and_write_summary(f'Error in {__file__}: {e}')
    except Exception as e:
        exit_on_error_and_write_summary(f'Error in {__file__} {error_message}: {e}')

if __name__ == '__main__':
    main()
