#!/usr/bin/env python3
"""Measure live route choices through the three local policy proxies."""

import argparse
import csv
import random
import statistics
import time
from pathlib import Path
from urllib.request import urlopen


POLICIES = {"user-first": 18085, "network": 18084, "profiled": 18083}
COUNTS = (1, 3, 12)


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--output", type=Path, required=True)
    parser.add_argument("--samples", type=int, default=300)
    args = parser.parse_args()
    args.output.mkdir(parents=True, exist_ok=True)
    rng = random.Random(20260927)

    for policy, port in POLICIES.items():
        for count in COUNTS:
            for _ in range(20):
                with urlopen(f"http://127.0.0.1:{port}/serial?count={count}", timeout=10):
                    pass

    trials = [(policy, count, repeat) for policy in POLICIES for count in COUNTS
              for repeat in range(args.samples)]
    rng.shuffle(trials)
    rows = []
    for policy, count, repeat in trials:
        started = time.perf_counter_ns()
        with urlopen(
            f"http://127.0.0.1:{POLICIES[policy]}/serial?count={count}", timeout=10
        ) as response:
            response.read()
            host = response.headers["X-Selected-Host"]
            status = response.status
        if status != 200:
            raise RuntimeError(f"{policy} N={count} returned HTTP {status}")
        rows.append({
            "policy": policy,
            "n": count,
            "repeat": repeat,
            "selected_host": host,
            "latency_ms": (time.perf_counter_ns() - started) / 1_000_000,
        })

    with (args.output / "routed-raw.csv").open("w", newline="") as output:
        writer = csv.DictWriter(output, fieldnames=rows[0].keys())
        writer.writeheader()
        writer.writerows(rows)
    summary = []
    for count in COUNTS:
        grouped = {
            policy: [row["latency_ms"] for row in rows
                     if row["policy"] == policy and row["n"] == count]
            for policy in POLICIES
        }
        profiled = grouped["profiled"]
        for policy in POLICIES:
            subset = [row for row in rows if row["policy"] == policy and row["n"] == count]
            hosts = sorted({row["selected_host"] for row in subset})
            summary.append({
                "policy": policy,
                "n": count,
                "selected_host": ",".join(hosts),
                "p50_ms": f"{statistics.median(row['latency_ms'] for row in subset):.6f}",
            })
        for baseline_name in ("user-first", "network"):
            baseline = grouped[baseline_name]
            deltas = []
            for _ in range(2000):
                base_sample = [baseline[rng.randrange(len(baseline))] for _ in baseline]
                prof_sample = [profiled[rng.randrange(len(profiled))] for _ in profiled]
                deltas.append(statistics.median(base_sample) - statistics.median(prof_sample))
            deltas.sort()
            summary.append({
                "policy": f"profiled_vs_{baseline_name}",
                "n": count,
                "selected_host": "",
                "p50_ms": f"{statistics.median(baseline) - statistics.median(profiled):.6f}",
                "ci95_low_ms": f"{deltas[50]:.6f}",
                "ci95_high_ms": f"{deltas[1949]:.6f}",
            })
    with (args.output / "routed-summary.csv").open("w", newline="") as output:
        writer = csv.DictWriter(
            output,
            fieldnames=("policy", "n", "selected_host", "p50_ms", "ci95_low_ms",
                        "ci95_high_ms"),
        )
        writer.writeheader()
        writer.writerows(summary)
    for row in summary:
        print(row)


if __name__ == "__main__":
    main()
