from .core import ask_openai, unroll_prompt_from_file
import subprocess
import tempfile
import os


def use_tree_command(directory):
    """
    Use the tree command to list the contents of a directory and return the output.

    Args:
        directory (str): The directory to list.
    """
    result = subprocess.run(["tree", directory], capture_output=True, text=True)
    return result.stdout


def execute_bash_command(bash_code, directory):
    # Create a temporary bash script file (not within the specified directory)
    with tempfile.NamedTemporaryFile(mode="w", suffix=".sh", delete=False) as temp_file:
        temp_file.write(bash_code)
        temp_file.flush()
        temp_filename = temp_file.name

    # Make the temporary script executable
    os.chmod(temp_filename, 0o755)

    try:
        # Execute the temporary bash script in the given directory
        result = subprocess.run(
            ["bash", temp_filename], cwd=directory, capture_output=True, text=True
        )
    finally:
        # Clean up the temporary file
        os.remove(temp_filename)

    return result.stdout


def refactor_code(replace_map, directory):
    refactor_prompt = unroll_prompt_from_file("Refactor.txt", unroll=True)

    for key, value in replace_map.items():
        refactor_prompt = refactor_prompt.replace(f"[{key}]", value)

    bash_file_code = ask_openai(refactor_prompt, "high")

    command_output = execute_bash_command(bash_file_code, directory)

    return bash_file_code, command_output


def summarize_work_done(replace_map, directory):
    summary_prompt = unroll_prompt_from_file("RefactorSummary.txt", unroll=True)

    for key, value in replace_map.items():
        summary_prompt = summary_prompt.replace(f"[{key}]", value)

    summary = ask_openai(summary_prompt, "high")

    return summary


def checkpoint_next_action(replace_map, directory):
    checkpoint_prompt = unroll_prompt_from_file(
        "CheckpointerRedirecter.txt", unroll=True
    )

    for key, value in replace_map.items():
        checkpoint_prompt = checkpoint_prompt.replace(f"[{key}]", value)

    result = ask_openai(checkpoint_prompt, "high")

    return result


def code_test_command(test_command, directory):
    try:
        result = subprocess.run(
            test_command.split(" "), cwd=directory, capture_output=True, text=True
        )
    except Exception as e:
        return f"An error occurred while executing the test command: {e}"

    if result.stdout or result.stderr:
        return (
            f"STDOUT:\n{result.stdout}\n"
            f"STDERR:\n{result.stderr}\n"
            f"Exit code: {result.returncode}"
        )
    else:
        return f"Program exited with code {result.returncode}"


def execute_major_coding_task(task_instruction, directory, test_command):
    """
    Execute a major coding task.

    Args:
        task_instruction (str): The task instruction.
        directory (str): The directory where the task will be executed
    """

    replace_map = {
        "TASK_INSTRUCTION_PLACEHOLDER": task_instruction,
        "TREE_COMMAND_PLACEHOLDER": use_tree_command(directory),
        "EXTRACTED_INFORMATION_PLACEHOLDER": "No extracted information yet",
        "SUMMARY_OF_WORK_DONE_PLACEHOLDER": "No work done yet, this is the first iteration",
        "TEST_OUTPUT_COMMAND": "No command was executed to test the code",
        "TEST_COMMAND": test_command,
    }

    while True:
        response = checkpoint_next_action(replace_map, directory)

        if response == "refactor":
            bash_file_code, command_output = refactor_code(replace_map, directory)
            replace_map["BASH_SCRIPT_PLACEHOLDER"] = bash_file_code
            summary_description = summarize_work_done(replace_map, directory)
            replace_map["SUMMARY_OF_WORK_DONE_PLACEHOLDER"] = summary_description
            replace_map["TEST_OUTPUT_COMMAND"] = code_test_command(
                test_command, directory
            )
            replace_map["TREE_COMMAND_PLACEHOLDER"] = use_tree_command(directory)

        elif response == "finish":
            return replace_map
