#!/usr/bin/env python3
"""Install the lightweight front door and switch only /code/ to the JD tunnel."""

from __future__ import annotations

import datetime
import pathlib
import re
import shutil
import subprocess
import sys
import urllib.error
import urllib.request


SITE_CONFIG = pathlib.Path("/etc/nginx/sites-enabled/guanghulab")
WEB_ROOT = pathlib.Path("/var/www/guanghulab-front-door")
SOURCE_FILES = ("index.html", "styles.css", "robots.txt", "llms.txt", "sitemap.xml")

OLD_CODE_BLOCK = re.compile(
    r"""    # Forgejo 代码仓库
    location /code/ \{
        auth_request /auth/verify-signature;
        proxy_pass http://127\.0\.0\.1:3001/;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;
        client_max_body_size 100m;
    \}
""",
)

NEW_CODE_BLOCK = """    # 光湖代码频道 · 广州备案前门 → 京东个人子频道
    location /code/ {
        proxy_pass http://127.0.0.1:18088/code/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_connect_timeout 5s;
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;
        client_max_body_size 256m;
    }
"""


def run(*args: str) -> None:
    subprocess.run(args, check=True)


def get_status(url: str) -> int:
    request = urllib.request.Request(url, method="GET")
    try:
        with urllib.request.urlopen(request, timeout=15) as response:
            return response.status
    except urllib.error.HTTPError as error:
        return error.code


def main() -> None:
    if len(sys.argv) != 2:
        raise SystemExit("usage: install-lite-front-door.py SOURCE_DIRECTORY")
    source = pathlib.Path(sys.argv[1]).resolve()
    if not SITE_CONFIG.is_file():
        raise RuntimeError("active guanghulab nginx config unavailable")
    for name in SOURCE_FILES:
        if not (source / name).is_file():
            raise RuntimeError(f"front-door source missing: {name}")

    current = SITE_CONFIG.read_text(encoding="utf-8")
    updated, replacements = OLD_CODE_BLOCK.subn(NEW_CODE_BLOCK, current)
    if replacements == 0 and NEW_CODE_BLOCK.strip() not in current:
        raise RuntimeError("expected legacy /code/ block not found")
    if replacements > 1:
        raise RuntimeError("multiple legacy /code/ blocks found")

    stamp = datetime.datetime.now(datetime.timezone.utc).strftime("%Y%m%dT%H%M%SZ")
    backup_root = pathlib.Path("/var/backups/guanghu/front-door") / stamp
    backup_root.mkdir(parents=True, mode=0o700)
    shutil.copy2(SITE_CONFIG, backup_root / "guanghulab.nginx")
    if WEB_ROOT.exists():
        shutil.copytree(WEB_ROOT, backup_root / "web-root")

    temporary_config = SITE_CONFIG.with_name(f"guanghulab.{stamp}.new")
    temporary_config.write_text(updated, encoding="utf-8")
    temporary_config.chmod(0o644)
    temporary_config.replace(SITE_CONFIG)

    WEB_ROOT.mkdir(parents=True, exist_ok=True)
    for name in SOURCE_FILES:
        destination = WEB_ROOT / name
        shutil.copy2(source / name, destination)
        destination.chmod(0o644)

    try:
        run("/usr/sbin/nginx", "-t")
        run("/usr/bin/systemctl", "reload", "nginx")
        if get_status("https://guanghulab.com/") != 200:
            raise RuntimeError("front-door homepage verification failed")
        if get_status("https://guanghulab.com/code/") not in (200, 303):
            raise RuntimeError("code-channel public route verification failed")
        if get_status("https://guanghulab.com/fifth-domain/api/v1/version") != 200:
            raise RuntimeError("legacy Fifth Domain verification failed")
    except Exception:
        shutil.copy2(backup_root / "guanghulab.nginx", SITE_CONFIG)
        if (backup_root / "web-root").exists():
            shutil.rmtree(WEB_ROOT)
            shutil.copytree(backup_root / "web-root", WEB_ROOT)
        run("/usr/sbin/nginx", "-t")
        run("/usr/bin/systemctl", "reload", "nginx")
        raise

    print(f"LIGHT_FRONT_DOOR_DEPLOYED backup={backup_root}")


if __name__ == "__main__":
    main()
