import ast
import json
import os
import re
import shutil
import sys
from concurrent.futures import ProcessPoolExecutor, as_completed
from multiprocessing import Process, cpu_count

from evalplus.eval.utils import (
    create_tempdir,
    reliability_guard,
    swallow_io,
    time_limit,
)




import pandas as pd


def suppress_output(func):
    def wrapper(*args, **kwargs):
        original_stdout = sys.stdout
        original_stderr = sys.stderr
        sys.stdout = open(os.devnull, "w")
        sys.stderr = sys.stdout
        try:
            result = func(*args, **kwargs)
        finally:
            sys.stdout.close()
            sys.stdout = original_stdout
            sys.stderr = original_stderr
        return result

    return wrapper


def _run(code) -> None:
    with create_tempdir():
        rmtree = shutil.rmtree
        rmdir = os.rmdir
        chdir = os.chdir
        getcwd = os.getcwd

        maximum_memory_bytes = 1 * 1024 * 1024 * 1024
        reliability_guard(maximum_memory_bytes=maximum_memory_bytes)


        with swallow_io():
            with time_limit(4):
                exec(code)

        shutil.rmtree = rmtree
        os.rmdir = rmdir
        os.chdir = chdir
        os.getcwd = getcwd


def containerized_run(item):
    import sys
    sys.path.append("...")
    from code_exec_reqs import exec_test

    idx, result, code, srv = item
    passed, _ = exec_test(srv, code, "", timeout=10)
    return (idx, result) if passed else None


def fork_run(item):
    idx, result, code, _ = item
    sys.stdout = open(os.devnull, "w")
    sys.stderr = sys.stdout
    p = Process(target=_run, args=(code,))
    p.start()
    p.join(timeout=10)
    return (idx, result) if p.exitcode == 0 else None


def is_compilable(code):
    try:
        ast.parse(code)
        return True
    except SyntaxError:
        return False


def extract_code(response):
    pattern = r"^```python\s*\n(.*?)(?=^```)"
    result = re.findall(pattern, response, re.DOTALL | re.MULTILINE)
    return "\n".join([x for x in result if is_compilable(x)])
