import json, subprocess, statistics, sys, datetime
from urllib.parse import urlparse
from playwright.sync_api import sync_playwright

EXE = sys.argv[1] if len(sys.argv) > 1 else None
VENDORS = [
  {"vendor": "CallRail", "site": "https://www.callrail.com/", "script": "https://cdn.callrail.com/companies/297407543/f6b60be971df89061219/12/swap.js", "hosts": ["callrail.com"]},
  {"vendor": "CallTrackingMetrics", "site": "https://www.calltrackingmetrics.com/", "script": "https://25.tctm.co/t.js", "hosts": ["tctm.co"]},
  {"vendor": "Mediahawk", "site": "https://www.mediahawk.co.uk/", "script": "https://static.trackedweb.net/js/_dmptv4.js", "hosts": ["trackedweb.net"]},
  {"vendor": "WhatConverts", "site": "https://www.whatconverts.com/", "script": "https://s.ksrndkehqnwntyxlhgto.com/51367.js", "hosts": ["ksrndkehqnwntyxlhgto.com"]},
  {"vendor": "Nimbata", "site": "https://www.nimbata.com/", "script": "https://cdn.dni.nimbata.com/65028045.min.js?v=2", "hosts": ["dni.nimbata.com"]},
  {"vendor": "Ruler Analytics", "site": "https://www.ruleranalytics.com/", "script": "https://ruler.nyltx.com/lib/1.0/ra-bootstrap.min.js", "hosts": ["nyltx.com"]},
  {"vendor": "CallTracker", "site": None, "script": "https://calltracker.dev/api/dni/snippet/" + (sys.argv[2] if len(sys.argv) > 2 else "<placement-id>"), "hosts": ["calltracker.dev"]},
]
UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0 Safari/537.36"

def curl_size(url, enc):
    args = ["curl", "-sS", "-L", "-o", "/dev/null", "-A", UA, "-w", "%{size_download} %{http_code} %{content_type}"]
    args += ["-H", f"Accept-Encoding: {enc}"]
    out = subprocess.run(args + [url], capture_output=True, text=True, timeout=60).stdout.split(" ", 2)
    return int(out[0]), out[1]

def decoded_size(url):
    out = subprocess.run(["curl", "-sS", "-L", "--compressed", "-A", UA, url], capture_output=True, timeout=60).stdout
    return len(out)

def header(url, name):
    out = subprocess.run(["curl", "-sS", "-L", "-D", "-", "-o", "/dev/null", "-A", UA, "-H", "Accept-Encoding: br, gzip", url], capture_output=True, text=True, timeout=60).stdout
    vals = [l.split(":", 1)[1].strip() for l in out.splitlines() if l.lower().startswith(name.lower() + ":")]
    return vals[-1] if vals else ""

def host_match(url, hosts):
    h = urlparse(url).netloc
    return any(h == x or h.endswith("." + x) for x in hosts)

rows = []
with sync_playwright() as p:
    browser = p.chromium.launch(executable_path=EXE) if EXE else p.chromium.launch()
    for v in VENDORS:
        wire, code = curl_size(v["script"], "br, gzip")
        decoded = decoded_size(v["script"])
        row = {"vendor": v["vendor"], "script_url": v["script"] if v["vendor"] != "CallTracker" else "https://calltracker.dev/api/dni/snippet/<placement-id>",
               "http_status": code, "script_bytes_transferred": wire, "script_bytes_decoded": decoded,
               "content_encoding": header(v["script"], "content-encoding") or "none", "cache_control": header(v["script"], "cache-control")}
        runs = []
        if v["site"]:
            for i in range(3):
                ctx = browser.new_context(user_agent=UA)
                page = ctx.new_page()
                hits = []
                page.on("requestfinished", lambda r, hits=hits, hosts=v["hosts"]: hits.append(r) if host_match(r.url, hosts) else None)
                page.goto(v["site"], wait_until="load", timeout=60000)
                page.wait_for_timeout(10000)
                total = 0
                for r in hits:
                    try:
                        s = r.sizes()
                        total += s["responseBodySize"] + s["responseHeadersSize"]
                    except Exception:
                        pass
                runs.append({"requests": len(hits), "bytes": total})
                ctx.close()
            row["onsite_runs"] = len(runs)
            row["onsite_requests_median"] = statistics.median(r["requests"] for r in runs)
            row["onsite_transfer_bytes_median"] = int(statistics.median(r["bytes"] for r in runs))
        else:
            row["onsite_runs"] = 0
            row["onsite_requests_median"] = None
            row["onsite_transfer_bytes_median"] = None
        rows.append(row)
        print(json.dumps(row), flush=True)
    browser.close()
json.dump({"measured_at": datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="seconds"), "rows": rows}, open("measure.json", "w"), indent=1)
