import os
from actions_logging.app_logging import logger
from terragrunt.constants import PLAN_FILE_OUTPUT, DESTROY_PLAN_FILE, PLAN_FILE_CANDIDATE, PLAN_FILE_CANDIDATE_OUTPUT, APPLY, DESTROY
from terragrunt.iac_commands import run_iac_command, diff_files
from github.env import exit_on_error_and_write_summary
from terragrunt.tg_common import download_file_from_s3

def check_apply_for_drift(work_dir, tool):
    """
    Check for drift by running IaC commands 'plan' and 'show-and-save' and then get plan changes.

    Args:
        work_dir (str): The working directory to run the commands in.
        tool (str): The IaC tool to use for running the commands.

    Returns:
        list or None: Returns the contents of the plan file if changes are detected, otherwise None.
    """
    run_iac_command(work_dir, tool, 'plan')
    run_iac_command(work_dir, tool, 'show-and-save')
    return get_plan_changes(work_dir)

def get_plan_changes(work_dir):
    """
    Read the plan file from the specified working directory and check for changes.

    Args:
        work_dir (str): The working directory containing the plan file.

    Returns:
        list or None: Returns the contents of the plan file if changes are detected, otherwise None.

    Raises:
        SystemExit: If an error occurs while reading the plan file.
    """
    try:
        with open(os.path.join(work_dir, PLAN_FILE_OUTPUT), 'r') as plan:
            plan_contents = plan.readlines()
            for line in plan_contents:
                if 'No changes' in line:
                    return None
            return plan_contents
    except Exception as e:
        exit_on_error_and_write_summary(f"something went wrong during checking changes after apply due to error: {e}")


def compare_plans_for_drift(work_dir, tool, bucket_name, plan_folder, exec_mode=APPLY, plan_version=''):
    """
    Compare the generated plan with a previously saved candidate plan to check for drift.

    Args:
        work_dir (str): The working directory where the plans are located.
        tool (str): The IaC tool to use ('terraform' or 'terragrunt').
        bucket_name (str): The name of the S3 bucket to download the candidate plan from.
        plan_folder (str): The folder in the S3 bucket where the plans are stored.
        exec_mode (str, optional): The execution mode ('apply' or 'destroy'). Defaults to 'apply'.
        plan_version (str, optional): The version of the plan. Defaults to ''.

    Returns:
        str or None: The output of the plan diff if there are differences, otherwise None.

    Raises:
        SystemExit: If an error occurs during the plan comparison process.
    """
    plan_file_name = f"{plan_version}.tfplan"
    if exec_mode == DESTROY:
        plan_file_name = DESTROY_PLAN_FILE
    s3_plan_file = os.path.join(plan_folder, plan_file_name)

    download_file_from_s3(bucket_name, s3_plan_file, os.path.join(work_dir, PLAN_FILE_CANDIDATE))
    logger.warning("saving candidate plan for comparison")
    run_iac_command(work_dir, tool, 'show-and-save-candidate')

    plan_diff = diff_files(work_dir, PLAN_FILE_CANDIDATE_OUTPUT, PLAN_FILE_OUTPUT)
    if plan_diff:
        logger.warning('!!! There is difference between prepared candidate plan and the currently generated one, please review the plan carefully before proceeding !!!')
        logger.warning(plan_diff)
    else:
        logger.info("Candiate plan and currently generated plans match. Review the changes to approve...")
    return plan_diff
