"""Corre los ejemplos de la semana y comprueba lo que se puede contar: nunca tiempos."""
import os
import pathlib
import subprocess
import unittest

HERE = pathlib.Path(__file__).parent
DATA = os.environ.get("DATA", "../../data")
MAPS = [f"{DATA}/mapas/miraflores.txt", f"{DATA}/mapas/lima-sur.txt", f"{DATA}/mapas/lima.txt"]


def run(*command):
    return subprocess.run(
        list(command), cwd=HERE, text=True, encoding="utf-8", errors="replace", stdin=subprocess.DEVNULL,
        stdout=subprocess.PIPE, stderr=subprocess.STDOUT, timeout=300,
    )


class Examples(unittest.TestCase):
    def test_structure_tests_pass(self):
        done = run("build/test_structures")
        self.assertEqual(done.returncode, 0, done.stdout)

    def test_programs_exit_cleanly(self):
        done = run("build/dijkstra_trace")
        self.assertEqual(done.returncode, 0, done.stdout)

    def test_counts_on_real_maps(self):
        """V nodos sacados, 2E aristas leídas, y cada entrada sale: los números de la tabla."""
        lines = run("build/dijkstra_counts", *MAPS).stdout.splitlines()
        self.assertEqual(len(lines), 4)
        for row in lines[1:]:
            nodes, edges, settled, reads, pushes, stale, peak, *_ = (int(float(x)) for x in row.split())
            self.assertEqual(settled, nodes)
            self.assertEqual(reads, 2 * edges)
            self.assertEqual(pushes, settled + stale)
            self.assertLessEqual(pushes, 2 * edges + 1)
            self.assertLessEqual(peak, pushes)

    def test_int_cannot_overflow_on_these_maps(self):
        """Ninguna ruta sin repetir nodos pasa de la suma de todas las aristas."""
        lines = run("build/distance_range", *MAPS).stdout.splitlines()
        limit = int(lines[0].split()[-1])
        for line in lines[2:]:
            parts = line.replace(",", "").split()
            total = int(parts[parts.index("todas") + 1])
            self.assertLess(total, limit)

    def test_public_tests_catch_nothing_written(self):
        """La carpeta de los estudiantes compila y se detiene en lo que falta."""
        done = subprocess.run(
            ["make", "--no-print-directory", "LAB_DIR=lab", "build/lab/lab_tests", "build/lab/optional_tests"],
            cwd=HERE, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
        )
        self.assertEqual(done.returncode, 0, done.stdout)
        self.assertNotIn("warning", done.stdout)


if __name__ == "__main__":
    unittest.main()
