"""Ayudas de la semana 11: levantar la topología y correr comandos en sus nodos."""
import os
import subprocess
import time
import unittest

HERE = os.path.dirname(os.path.abspath(__file__))
FOLDER = os.path.join(HERE, "dumbbell")
TOPOLOGY = "dumbbell.clab.yml"
PREFIX = "clab-w11-dumbbell-"
NETWORK = "redes-w11"
RECEIVER = "10.211.4.10"


def deploy():
    done = subprocess.run(["containerlab", "deploy", "-t", TOPOLOGY, "--reconfigure"],
                          cwd=FOLDER, capture_output=True, text=True, timeout=300)
    if done.returncode != 0:
        raise RuntimeError(done.stdout + done.stderr)


def destroy():
    subprocess.run(["containerlab", "destroy", "-t", TOPOLOGY, "--cleanup"],
                   cwd=FOLDER, capture_output=True, text=True, timeout=300)
    subprocess.run(["docker", "network", "rm", NETWORK], capture_output=True, text=True)


def sh(node, command, timeout=120, check=True):
    """Corre un comando de shell en un nodo y devuelve su stdout."""
    done = subprocess.run(["docker", "exec", PREFIX + node, "sh", "-c", command],
                          capture_output=True, text=True, timeout=timeout)
    if check and done.returncode != 0:
        raise RuntimeError(f"{node}: {command}\n{done.stdout}{done.stderr}")
    return done.stdout


def spawn(node, command):
    """Arranca un comando en un nodo sin esperarlo; su stdout queda en un pipe."""
    return subprocess.Popen(["docker", "exec", PREFIX + node, "sh", "-c", command],
                            stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)


def wait_until(predicate, seconds=30, step=0.5):
    """Espera a que una condición se cumpla; devuelve si se cumplió."""
    deadline = time.monotonic() + seconds
    while time.monotonic() < deadline:
        if predicate():
            return True
        time.sleep(step)
    return predicate()


def load_metrics():
    """Devuelve lab/metrics.py (o la solución, si existe); salta si sigue con el TODO."""
    import importlib.util
    folder = os.path.join(HERE, "solution")
    if not os.path.isdir(folder):
        folder = os.path.join(HERE, "lab")
    path = os.path.join(folder, "metrics.py")
    with open(path, encoding="utf-8") as file:
        if "TODO" in file.read():
            raise unittest.SkipTest("falta completar lab/metrics.py")
    spec = importlib.util.spec_from_file_location("metrics", path)
    module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(module)
    return module
