import re
from actions_logging.app_logging import logger
from github.env import get_required_env_var, exit_on_error_and_write_summary
from github.github_apis import get_changed_files
from env_files.constants import MINOR, PATCH, MAJOR, GLOBAL_FILE, DEFAULT_ENV_FILES_PATH


NO_CHANGES = "No changes"

def get_diff_for_changed_env_files(env_files_path: str):
    try:
        pr_number = get_required_env_var("PR_NUMBER")
        repo = get_required_env_var("GITHUB_REPOSITORY")
        pr_files = get_changed_files(repo, pr_number)
        changed_env_files = [file for file in pr_files if file['filename'].startswith(env_files_path)]
        changes = {}
        semver_level = NO_CHANGES
        for filename_to_filter in changed_env_files:
            logger.debug(f"filename_to_filter: {filename_to_filter}")
            file_name = filename_to_filter['filename']
            if file_name.startswith(env_files_path):
                if not filename_to_filter.get('patch'):
                    # patch is the value of the change in the file for example:
                    # '@@ -4,5 +4,5 @@\n   "CONNECTOR_ROLE_ARN": "gggggggggglobal",\n'
                    logger.debug(f"no patch in {filename_to_filter}")
                    continue
                semver, message = get_change_level(filename_to_filter['patch'])
                changes[file_name] = message
                if semver_level == MAJOR:
                    continue
                if file_name.endswith(GLOBAL_FILE) and semver != NO_CHANGES:
                    semver_level = MAJOR
                    continue

                if semver_level == MINOR:
                    continue

                if semver_level in [NO_CHANGES, PATCH] and semver == MINOR:
                    semver_level = MINOR
                    continue

                if semver_level == NO_CHANGES and semver == PATCH:
                    semver_level = PATCH
                    continue
        return semver_level, changes

    except Exception as e:
        exit_on_error_and_write_summary(f"error in get_diff_for_changed_env_files {e}")


def get_change_level(patch: str) -> tuple[str, list]:
    try:
        old_values = re.findall(r'^- *(.*)', patch, re.MULTILINE)
        new_values = re.findall(r'^\+ *(.*)', patch, re.MULTILINE)

        def to_dict(values):
            result = {}
            for line in values:
                if ':' in line:
                    key, value = line.split(':', 1)
                    key = key.strip(' ,"')
                    value = value.strip(' ,"')
                    result[key] = value
            return result

        old_dict = to_dict(old_values)
        new_dict = to_dict(new_values)

        key_changed = False
        value_changed = False
        changes = []

        # Check for keys removed or added
        for key in set(old_dict.keys()).union(new_dict.keys()):
            if key in old_dict and key in new_dict:
                if old_dict[key] != new_dict[key]:
                    value_changed = True
                    changes.append(f"Value of key '{key}' changed")
            elif key in old_dict and key not in new_dict:
                key_changed = True
                changes.append(f"Key '{key}' was removed")
            elif key in new_dict and key not in old_dict:
                key_changed = True
                changes.append(f"Key '{key}' was added'")

        if key_changed:
            return MINOR, changes
        elif value_changed:
            return PATCH, changes
        else:
            return NO_CHANGES, []

    except Exception as e:
        exit_on_error_and_write_summary(f"Error in get_change_level: {e}")


if __name__ == '__main__':
    get_diff_for_changed_env_files(DEFAULT_ENV_FILES_PATH)
