"""TLS-Status + Renewal für SUPER_ADMIN.

Server-lokal – jede Installation (137/164) kennt nur ihr eigenes Zertifikat,
kein Cross-Server-Wissen (siehe CLAUDE.md: Server sind entkoppelt).

Erkennt drei Modi:
  - "proxy"    – kein lokal verwaltetes Zertifikat, vorgeschalteter Proxy
                 terminiert TLS (aktueller Standardfall)
  - "certbot"  – öffentliches Let's-Encrypt-Zertifikat (setup-tls.sh)
  - "internal" – eigene interne CA (setup-tls-internal.sh)
"""
import re
import subprocess
from pathlib import Path
from typing import Any

LETSENCRYPT_LIVE = Path("/etc/letsencrypt/live")
INTERNAL_CA_DIR = Path("/etc/nginx/internal-ca")
SETUP_TLS_SCRIPT = Path("/opt/timemaster/setup-tls.sh")
SETUP_TLS_INTERNAL_SCRIPT = Path("/opt/timemaster/setup-tls-internal.sh")

_DOMAIN_RE = re.compile(r"^[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)+$")
_IP_RE = re.compile(r"^\d{1,3}(\.\d{1,3}){3}$")


def _cert_enddate(cert_path: Path) -> str | None:
    try:
        out = subprocess.run(
            ["openssl", "x509", "-enddate", "-noout", "-in", str(cert_path)],
            capture_output=True, text=True, timeout=5, check=True,
        )
    except (subprocess.CalledProcessError, FileNotFoundError, subprocess.TimeoutExpired):
        return None
    # Format: "notAfter=Aug  5 12:00:00 2027 GMT"
    return out.stdout.strip().removeprefix("notAfter=") or None


def get_tls_status() -> dict[str, Any]:
    if LETSENCRYPT_LIVE.is_dir():
        for entry in LETSENCRYPT_LIVE.iterdir():
            cert = entry / "cert.pem"
            if cert.exists():
                return {
                    "mode": "certbot",
                    "domain": entry.name,
                    "valid_until": _cert_enddate(cert),
                    "renewable": True,
                }

    internal_cert = INTERNAL_CA_DIR / "server.crt"
    if internal_cert.exists():
        return {
            "mode": "internal",
            "domain": None,
            "valid_until": _cert_enddate(internal_cert),
            "renewable": True,
            "ca_cert_path": str(INTERNAL_CA_DIR / "ca.crt"),
        }

    return {
        "mode": "proxy",
        "domain": None,
        "valid_until": None,
        "renewable": False,
    }


def renew_certbot(domain: str) -> str:
    if not _DOMAIN_RE.match(domain):
        raise ValueError("Ungültiger Domain-Name")
    if not SETUP_TLS_SCRIPT.exists():
        raise RuntimeError("setup-tls.sh nicht gefunden")
    result = subprocess.run(
        [str(SETUP_TLS_SCRIPT), domain],
        capture_output=True, text=True, timeout=120,
    )
    if result.returncode != 0:
        raise RuntimeError(result.stderr[-2000:] or result.stdout[-2000:])
    return result.stdout[-4000:]


def renew_internal(hostname: str, ip: str | None) -> str:
    if not _DOMAIN_RE.match(hostname) and not _IP_RE.match(hostname):
        raise ValueError("Ungültiger Hostname")
    if ip and not _IP_RE.match(ip):
        raise ValueError("Ungültige IP")
    if not SETUP_TLS_INTERNAL_SCRIPT.exists():
        raise RuntimeError("setup-tls-internal.sh nicht gefunden")
    args = [str(SETUP_TLS_INTERNAL_SCRIPT), hostname]
    if ip:
        args.append(ip)
    result = subprocess.run(args, capture_output=True, text=True, timeout=60)
    if result.returncode != 0:
        raise RuntimeError(result.stderr[-2000:] or result.stdout[-2000:])
    subprocess.run(["systemctl", "reload", "nginx"], capture_output=True, timeout=10)
    return result.stdout[-4000:]
