#!/usr/bin/env python3
import io, re, sys, zipfile, tempfile, os
from pathlib import Path
from urllib.request import Request, urlopen

URL = "https://kb.nssurge.com/surge-knowledge-base/release-notes/snell"
BASE = "https://dl.nssurge.com/snell"
PATTERNS = {
    "v4": r"snell-server-(v4\.[0-9.]+)-linux-amd64\.zip",
    "v5": r"snell-server-(v5\.[0-9.]+)-linux-amd64\.zip",
}
TARGET = Path(".")

def get(url: str) -> bytes:
    return urlopen(Request(url, headers={"User-Agent": "Mozilla/5.0"}), timeout=60).read()

def latest(html: str, major: str) -> str:
    vs = re.findall(PATTERNS[major], html)
    if not vs:
        raise RuntimeError(f"未找到 {major} 版本")
    return max(set(vs), key=lambda s: tuple(map(int, s[1:].split("."))))

def unzip_binary(data: bytes) -> bytes:
    with zipfile.ZipFile(io.BytesIO(data)) as z:
        for name in z.namelist():
            if name.endswith("/snell-server") or name == "snell-server":
                return z.read(name)
    raise RuntimeError("压缩包中未找到 snell-server")

def write_atomic(path: Path, data, mode: int) -> None:
    with tempfile.NamedTemporaryFile(dir=path.parent, delete=False, mode="wb" if isinstance(data, bytes) else "w") as f:
        f.write(data)
        f.flush()
        os.chmod(f.name, mode)
        Path(f.name).replace(path)

def process(html: str, major: str) -> None:
    ver = latest(html, major)
    vf = TARGET / f"snell-server-{major}-version"
    local = vf.read_text().strip() if vf.exists() else ""
    print(f"[{major}] remote={ver} local={local or '(none)'}")
    if local == ver:
        print(f"[{major}] already up to date")
        return
    zip_name = f"snell-server-{ver}-linux-amd64.zip"
    binary = unzip_binary(get(f"{BASE}/{zip_name}"))
    print(f"[{major}] {ver} download and unzip ok")
    write_atomic(TARGET / f"snell-server-{major}-linux-amd64", binary, 0o755)
    print(f"[{major}] {ver} binary ok")
    write_atomic(vf, ver + "\n", 0o644)
    print(f"[{major}] {ver} version file ok")

def main() -> int:
    try:
        html = get(URL).decode("utf-8", "replace")
        for major in ("v4", "v5"):
            process(html, major)
        return 0
    except Exception as e:
        print(f"失败: {e}", file=sys.stderr)
        return 1

if __name__ == "__main__":
    raise SystemExit(main())