import os
from github.get_file_from_github import get_file_from_github
from github.github_apis import get_git_all_tags
from github.constants import OWNER
from aws.constants import DEV_ENVS_IN_PRODUCTION_ACCOUNT, DEV_ENVS
from master.calculate_version import get_version
from actions_logging.app_logging import logger
from github.env import (exit_on_error_and_write_summary, write_github_env, get_required_env_var)
from env_files.constants import GLOBAL_FILE, MINOR, PATCH
from common.common import load_json_data


def get_severity_from_dicts_diff(old_dict, new_dict):
    try:
        old_keys = set(old_dict.keys())
        new_keys = set(new_dict.keys())
        if old_keys - new_keys or new_keys - old_keys:
            logger.debug(f"old_keys: {old_keys} new_keys: {new_keys}")
            logger.debug(f"old_keys - new_keys: {old_keys - new_keys}")
            logger.debug(f"new_keys - old_keys: {new_keys - old_keys}")
            return MINOR
        for key in old_keys & new_keys:
            if old_dict[key] != new_dict[key]:
                return PATCH
        return None
    except Exception as e:
        exit_on_error_and_write_summary(f"Error in get_semver_from_dicts_diff: {e}")


def get_semver_from_dicts_diff(old_dict, new_dict):
    try:
        changes = []
        severity = None
        old_keys = set(old_dict.keys())
        new_keys = set(new_dict.keys())
        for key in old_keys & new_keys:
            if old_dict[key] != new_dict[key]:
                changes.append(f"The value of key '{key}' has changed")
                if severity != MINOR:
                    severity = PATCH

        # Check for removed or changed keys (Minor severity)
        for key in old_keys - new_keys:
            changes.append(f"The key '{key}' was removed")
            severity = MINOR

        # Check for new keys (Minor severity)
        for key in new_keys - old_keys:
            changes.append(f"The key '{key}' is new")
            severity = MINOR
        return severity, changes
    except Exception as e:
        exit_on_error_and_write_summary(f"Error in get_semver_from_dicts_diff: {e}")


def check_diff_and_severity(file_name: str, old_file_name: str)-> tuple[str, list[str]]:
    try:
        logger.info(f"comparing file_name: {file_name} old_file_name: {old_file_name}")
        if not file_name or not old_file_name:
            exit_on_error_and_write_summary("file_name or old_file_name is empty")
        old_json = load_json_data(old_file_name)
        new_json = load_json_data(file_name)
        severity, changes = get_semver_from_dicts_diff(old_json, new_json)
        return severity, changes

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

def check_tag_existence(full_repo_name:str, version:str, tag_safix:str)-> list[str]:
    try:
        tags = []
        tags = get_git_all_tags(full_repo_name, tag_safix, tags)
        logger.info(f"env tags: {tags}")
        if version not in tags:
            exit_on_error_and_write_summary(f" version {version} not found in tags and it should be there")
        else:
            logger.info(f"version {version} found in tags")
            return tags
    except Exception as e:
        exit_on_error_and_write_summary(f" error in check_tag_existence: {e}")


def main():
    try:
        owner = OWNER
        repo = get_required_env_var("REPO_NAME")
        env_name = get_required_env_var("ENV_NAME")
        env_files_path = os.getenv("ENV_FILES_PATH", ".github/env_files")
        tag_safix = f"ENV_{env_name}"
        version = get_required_env_var("ENV_FILE_VERSION")
        full_repo_name = os.path.join(owner,repo)
        sub_folder = env_name
        if env_name in DEV_ENVS + DEV_ENVS_IN_PRODUCTION_ACCOUNT:
            sub_folder = os.path.join(f"dev",env_name)

        tags = check_tag_existence(full_repo_name, version, tag_safix)
        get_file_from_github(f"{OWNER}/{repo}",os.path.join(env_files_path,f"{sub_folder}.json"), f".",ref=version)
        severity,changes = check_diff_and_severity(os.path.join(env_files_path,f"{sub_folder}.json"), f"{env_name}.json")
        get_file_from_github(f"{OWNER}/{repo}", os.path.join(env_files_path,GLOBAL_FILE), f".", ref=version)
        global_severity, global_changes = check_diff_and_severity(os.path.join(env_files_path,GLOBAL_FILE), GLOBAL_FILE)
        if severity == MINOR or global_severity == MINOR:
            severity = MINOR
        elif severity == PATCH or global_severity == PATCH:
            severity = PATCH
        else:
            logger.warning("No changes found")
            logger.warning("keep creating new .env file but not creating new version")
        if severity:
            clean_global_changes = " ".join(global_changes).replace(",", " ")
            changes_changes = " ".join(changes).replace(",", " ")
            changes = f"{GLOBAL_FILE}: {clean_global_changes} {env_name}.json: {changes_changes}"
            logger.info(f"Changes from current version: {changes}")
            logger.info(f"Severity: {severity}")
            new_version = get_version(version,tag_safix)
            new_version.bump_one(severity)
            if tag_safix:
                new_version = f"{new_version}-{tag_safix}"
            if new_version in tags:
                exit_on_error_and_write_summary(f"Version {new_version} already exists in tags")
            logger.info(f"GREEN_BG old version: {version} new version: {new_version}")
            write_github_env(new_version, "VERSION")
            write_github_env(severity, "ENV_FILE_SEVERITY")
            write_github_env(changes, "ENV_FILE_CHANGES")
            os.remove(f"{env_name}.json")
            os.remove(GLOBAL_FILE)
    except Exception as e:
        exit_on_error_and_write_summary(f"Error in main: {e}")

if __name__ == '__main__':
    main()
