from pathlib import Path
import importlib.util
import subprocess
import sys
import time

SCRIPT_DIR = Path(__file__).resolve().parent
DOWNLOADER = SCRIPT_DIR / "downloader.py"
PRODUCT_BUILDER = SCRIPT_DIR / "build_products.py"
RASTER_GENERATOR = SCRIPT_DIR / "raster_generator.py"
PRESSURE_ISOLINE_GENERATOR = SCRIPT_DIR / "pressure_isoline_generator.py"

STEP_DEPENDENCIES = {
    "Display Downloader": ("requests",),
    "Display Product Builder": tuple(),
    "Display Raster Generator": ("cfgrib", "mercantile", "numpy", "xarray"),
    "Pressure Isoline Generator": ("mercantile", "mapbox_vector_tile", "numpy"),
}


def check_dependencies():
    missing = []
    for step_name, modules in STEP_DEPENDENCIES.items():
        missing_modules = [module for module in modules if importlib.util.find_spec(module) is None]
        if missing_modules:
            missing.append(f"{step_name}: {', '.join(missing_modules)}")
    return missing


def run_step(name, script_path):
    print("\n==========================")
    print("Running:", name)
    print("==========================\n")

    start = time.time()
    command = [sys.executable, "-u", "-m", f"src.display.{script_path.stem}"]

    process = subprocess.Popen(
        command,
        cwd=str(SCRIPT_DIR.parent.parent),
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        text=True,
        bufsize=1,
    )

    assert process.stdout is not None
    for line in process.stdout:
        print(line, end="")

    return_code = process.wait()
    if return_code != 0:
        raise RuntimeError(f"{name} failed with exit code {return_code}")

    end = time.time()
    print("\nFinished:", name)
    print("Time:", round(end - start, 2), "seconds")


def main():
    print("Display Product Pipeline Starting...")
    print("Date:", time.strftime("%Y-%m-%d %H:%M:%S"))

    missing_dependencies = check_dependencies()
    if missing_dependencies:
        print("\n" + "!" * 50)
        print("Pipeline Failed: missing runtime dependencies")
        for item in missing_dependencies:
            print("-", item)
        print("!" * 50)
        raise SystemExit(1)

    try:
        run_step("Display Downloader", DOWNLOADER)
        run_step("Display Product Builder", PRODUCT_BUILDER)
        run_step("Display Raster Generator", RASTER_GENERATOR)
        run_step("Pressure Isoline Generator", PRESSURE_ISOLINE_GENERATOR)
        print("\n" + "=" * 50)
        print("Display Product Pipeline Completed Successfully!")
        print("=" * 50)
    except RuntimeError as exc:
        print("\n" + "!" * 50)
        print("Pipeline Failed:", str(exc))
        print("!" * 50)
        raise SystemExit(1)


if __name__ == "__main__":
    main()
