#!/usr/bin/env python3
"""Apply a bounded Redis 5 single-host baseline without printing its password."""

import argparse
import re
import shutil
from pathlib import Path

from render_cloud_sql import load_env, required


SAFE_MEMORY_RE = re.compile(r"^[1-9][0-9]*(mb|gb)$")


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--config", type=Path, required=True)
    parser.add_argument("--project-env", type=Path, required=True)
    parser.add_argument("--secrets-env", type=Path, required=True)
    parser.add_argument("--backup", type=Path, required=True)
    args = parser.parse_args()

    values = load_env(args.project_env)
    values.update(load_env(args.secrets_env))
    bind = required(values, "REDIS_BIND")
    port = required(values, "REDIS_PORT")
    maxmemory = required(values, "REDIS_MAXMEMORY").lower()
    policy = required(values, "REDIS_MAXMEMORY_POLICY")
    password = required(values, "REDIS_PASSWORD")
    if bind != "127.0.0.1":
        raise ValueError("single-host V1 requires REDIS_BIND=127.0.0.1")
    if port != "6379":
        raise ValueError("single-host V1 requires REDIS_PORT=6379")
    if not SAFE_MEMORY_RE.fullmatch(maxmemory):
        raise ValueError("REDIS_MAXMEMORY must look like 2048mb or 2gb")
    if policy not in {"allkeys-lru", "volatile-lru", "noeviction"}:
        raise ValueError("unsupported REDIS_MAXMEMORY_POLICY")
    if any(char.isspace() for char in password) or '"' in password or "'" in password:
        raise ValueError("REDIS_PASSWORD must not contain whitespace or quotes")

    settings = {
        "bind": bind,
        "protected-mode": "yes",
        "port": port,
        "daemonize": "no",
        "supervised": "systemd",
        "timeout": "0",
        "tcp-keepalive": "300",
        "databases": "16",
        "maxmemory": maxmemory,
        "maxmemory-policy": policy,
        "appendonly": "yes",
        "appendfsync": "everysec",
        "requirepass": password,
    }
    lines = args.config.read_text(encoding="utf-8").splitlines()
    output = []
    applied = set()
    for line in lines:
        stripped = line.strip()
        if not stripped or stripped.startswith("#"):
            output.append(line)
            continue
        key = stripped.split(None, 1)[0]
        if key in settings:
            if key not in applied:
                output.append(f"{key} {settings[key]}")
                applied.add(key)
            continue
        output.append(line)
    for key, value in settings.items():
        if key not in applied:
            output.append(f"{key} {value}")

    args.backup.parent.mkdir(parents=True, exist_ok=True)
    shutil.copy2(args.config, args.backup)
    args.config.write_text("\n".join(output) + "\n", encoding="utf-8")
    args.config.chmod(0o640)
    return 0


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