import queue
import time
import subprocess
import os
from multiprocessing import Process, Queue, current_process
import warnings
import logging
# ------------------------------------------------------------------------------------------
warnings.filterwarnings("ignore")
logging.captureWarnings(True)
# ------------------------------------------------------------------------------------------
def execute_bash(tasks_to_accomplish, tasks_that_are_done):
    """Execute bash job scripts in parallel."""
    while True:
        try:
            task = tasks_to_accomplish.get_nowait()
        except queue.Empty:
            break
        else:
            try:
                # Run the bash script
                subprocess.run(f"bash {task}", shell=True, check=True)
                
                # Report successful execution
                msg = f"{task} executed successfully by {current_process().name}"
                tasks_that_are_done.put(msg)
                print(msg)

                # Remove the submitted script only after successful execution
                if os.path.exists(task):
                    os.remove(task)
                    print(f"Deleted script: {task}")

            except subprocess.CalledProcessError as e:
                print(f"Error executing bash for {task}: {e}")

            # Short delay to prevent CPU overload
            time.sleep(0.01)
# ------------------------------------------------------------------------------------------
def parallel_bash_execution(list_of_sh_files, NparCalcs=4):
    """Run bash calculations in parallel using multiprocessing."""
    tasks_to_accomplish = Queue()
    tasks_that_are_done = Queue()
    processes = []

    # Load all tasks into the queue
    for sh_file in list_of_sh_files:
        tasks_to_accomplish.put(sh_file)

    # Create and start worker processes
    for _ in range(NparCalcs):
        p = Process(target=execute_bash, args=(tasks_to_accomplish, tasks_that_are_done))
        processes.append(p)
        p.start()

    # Wait for all processes to finish
    for p in processes:
        p.join()

    # Display completed tasks
    while not tasks_that_are_done.empty():
        print(tasks_that_are_done.get())

# ------------------------------------------------------------------------------------------
# Example usage:
# import glob
# cases_list = ['stage2' + str(i+1).zfill(5) for i in range(45)]
# output_files = sorted(glob.glob("stage2[0-9][0-9][0-9][0-9][0-9].out"))
# shfiles_to_send = [ibname + '.sh' for ibname in cases_list if ibname + '.out' not in output_files]
# parallel_bash_execution(shfiles_to_send, NparCalcs=2)
