"""Check every href/src in the META 2027 local mirror against the live web.

GET is used because several OJS and external endpoints do not implement HEAD correctly.
No forms are submitted and URL fragments are removed before network checks.
"""

from concurrent.futures import ThreadPoolExecutor, as_completed
from html import unescape
from pathlib import Path
import re
import subprocess
from urllib.parse import urldefrag, urljoin, urlparse

BASE = "https://metaconferences.org/META27/"
pages = sorted(p for p in Path(".").glob("*.html") if p.name not in {
    "compare-cards.html", "meta26_program_inject.html", "test-cards.html"
})

sources: dict[str, set[str]] = {}
for page in pages:
    html = page.read_text(encoding="utf-8")
    for raw in re.findall(r'''(?:href|src)=["']([^"']+)["']''', html, re.I):
        raw = unescape(raw.strip())
        if not raw or raw.startswith(("#", "mailto:", "tel:", "javascript:", "data:")):
            continue
        url = urldefrag(urljoin(BASE, raw))[0]
        if url in {"https://fonts.googleapis.com", "https://fonts.gstatic.com"}:
            continue  # resource-hint origins, not navigational links
        sources.setdefault(url, set()).add(page.name)


def check(url: str) -> tuple[str, int, str, str]:
    command = [
        "curl", "-ksSL", "--http1.1", "--compressed", "--connect-timeout", "6", "--max-time", "20",
        "-A", "META2027-link-audit/1.0", "-o", "/dev/null",
        "-w", "%{http_code}\t%{url_effective}", url,
    ]
    result = subprocess.run(command, capture_output=True, text=True)
    if result.returncode:
        return url, 0, "", f"curl:{result.returncode} {result.stderr.strip()}"
    code_text, _, final = result.stdout.partition("\t")
    return url, int(code_text or 0), final, ""


results = []
with ThreadPoolExecutor(max_workers=12) as executor:
    futures = {executor.submit(check, url): url for url in sorted(sources)}
    for future in as_completed(futures):
        results.append(future.result())

broken = []
blocked = []
redirected = []
for url, code, final, error in sorted(results):
    origin = urlparse(url).netloc
    internal = origin in {"metaconferences.org", "www.metaconferences.org"}
    if error or code == 0 or code >= 500 or code == 404:
        broken.append((url, code, final, error))
    elif code in {401, 403, 405, 418, 429, 451} and not internal:
        blocked.append((url, code, final, error))
    elif final and urldefrag(final)[0].rstrip("/") != url.rstrip("/"):
        redirected.append((url, code, final, error))

print(f"pages={len(pages)} unique_urls={len(results)} broken={len(broken)} blocked_external={len(blocked)} redirects={len(redirected)}")
for label, group in (("BROKEN", broken), ("BLOCKED_EXTERNAL", blocked)):
    for url, code, final, error in group:
        print(f"{label}\t{code}\t{url}\tfrom={','.join(sorted(sources[url]))}\tfinal={final}\t{error}")

internal_redirects = [r for r in redirected if urlparse(r[0]).netloc in {"metaconferences.org", "www.metaconferences.org"}]
for url, code, final, _ in internal_redirects:
    print(f"INTERNAL_REDIRECT\t{code}\t{url}\tfrom={','.join(sorted(sources[url]))}\tfinal={final}")
