import glob
import os
from pathlib import Path

from actions_logging.app_logging import logger
from validation.data import is_valid_json_string
from env_files.constants import KNOWN_FE_BUILD_PREFIXES
from github.env import exit_on_error_and_write_summary


def replace_placeholder_to_value(key_vals: dict, filepath: str, placeholder_prefix: str = "PLACEHOLDER_"):
    """
    Replaces placeholder strings in a file with corresponding values from a dictionary.

    This function reads the content of a file, searches for placeholders with a specific prefix,
    and replaces them with the corresponding values from the provided dictionary. If the value
    is a valid JSON string, it ensures the replacement is properly formatted.

    Args:
        key_vals (dict): A dictionary where keys are placeholder names (without the prefix)
                         and values are the replacement values.
        filepath (str): The path to the file where placeholders need to be replaced.
        placeholder_prefix (str, optional): The prefix used to identify placeholders in the file.
                                            Defaults to "PLACEHOLDER_".

    Raises:
        Exception: If an error occurs while reading, modifying, or writing the file.

    Notes:
        - Placeholders in the file should be prefixed with the `placeholder_prefix` followed by the key.
        - If a value is a valid JSON string, it will be wrapped in single quotes during replacement.
        - The function logs the replacement process and any errors encountered.
    """
    try:
        logger.info_green(f"parsing {filepath} placeholders")
        content = Path(filepath).read_text(encoding="utf-8")

        modified = False
        for key, value in key_vals.items():
            if f"{placeholder_prefix}{key}" in content:
                logger.info_green(f"Replacing {key} placeholder with value {value} in {filepath}")
                if is_valid_json_string(value):
                    content = content.replace(f'"{placeholder_prefix}{key}"', f"'{value}'")
                else:
                    content = content.replace(f"{placeholder_prefix}{key}", value)
                modified = True

        if modified:
            Path(filepath).write_text(content, encoding="utf-8")
    except Exception as e:
        logger.error_red_bg(f"Error while replacing env vars in {filepath}: {e}")


def replace_all_placeholders(base_path: str):
    """
    Replaces placeholder values in files with corresponding environment variable values.

    This function iterates over a predefined list of environment variable prefixes
    (`KNOWN_FE_BUILD_PREFIXES`) and searches for environment variables that start
    with each prefix. It then finds files matching the specified `base_path` pattern
    and replaces placeholders in those files with the corresponding environment
    variable values.

    Args:
        base_path (str): The base path or glob pattern to search for files
                         containing placeholders.

    Logs:
        - Logs the prefixes being searched for in environment variables.
        - Logs the number of matching files found for the given base path.
        - Logs warnings if no environment variables or files are found.

    Notes:
        - The function assumes the existence of `KNOWN_FE_BUILD_PREFIXES`,
          `replace_placeholder_to_value`, and `logger` in the global scope.
        - Placeholders in files are replaced using the `replace_placeholder_to_value` function.
    """
    try:
        logger.info_green(f"Will replace placeholders in: {files_to_parse}")
        for prefix in KNOWN_FE_BUILD_PREFIXES:
            logger.info(f"looking for variables with key prefixed with '{prefix}'")
            # Get all environment variables that start with the prefix, not __include__ it.
            env_vars = {k: v for k, v in os.environ.items() if k.startswith(prefix)}
            if not env_vars:
                logger.info_yellow(f"No env vars found with prefix '{prefix}' in keys")
                continue
            matching_files = glob.glob(base_path, recursive=True)
            if not matching_files:
                logger.warning(f"No files found matching pattern: {base_path}")
                return
            logger.info(f"Found {len(matching_files)} matching files")
            for filepath in matching_files:
                replace_placeholder_to_value(env_vars, filepath)
    except Exception as e:
        exit_on_error_and_write_summary(f"Error while replacing env vars: {e}")


if __name__ == "__main__":
    files_to_parse = os.getenv("BASE_REPLACE_PATH", "build/**/*.js")
    replace_all_placeholders(files_to_parse)
