#!/usr/bin/env bash
# Read/write run.config.json under RUN_DIR (.run/ for config layout).

save_config_json() {
  local answers_path="$1"
  local target="${WORKSPACE_CONFIG:?}"
  python3 - "${target}" "${answers_path}" <<'PY'
import json, os, re, sys

target, answers_path = sys.argv[1], sys.argv[2]
answers = {}
with open(answers_path, encoding="utf-8") as fh:
    for line in fh:
        line = line.rstrip("\n")
        if "=" not in line:
            continue
        key, value = line.split("=", 1)
        answers[key] = value

data = {}
if os.path.isfile(target):
    with open(target, encoding="utf-8") as fh:
        existing = json.load(fh)
    if isinstance(existing, dict):
        data.update({k: v for k, v in existing.items() if k.startswith("_")})

for key, value in answers.items():
    if value in ("true", "false"):
        data[key] = value == "true"
    elif value.isdigit():
        data[key] = int(value)
    else:
        data[key] = value

# Grouped the way the questions are asked, as an object per section, so the
# file reads top to bottom instead of as one flat alphabetical list. Keys keep
# their names: the sections are for reading, and everything that consumes the
# config still looks up a plain key.
GROUPS = [
    ("project", ["COMPOSE_PROJECT_NAME", "PROJECT_LABEL"]),
    ("repositories", ["BACKEND_DIR", "BACKEND_SUBDIR", "FRONTEND_DIR"]),
    ("backend", ["BACKEND_STACK", "BACKEND_INSTALL_CMD", "BACKEND_BUILD_CMD",
                 "BACKEND_START_CMD", "BACKEND_MIGRATE_CMD", "BACKEND_SEED_CMD",
                 "BACKEND_QUEUE_CMD", "BACKEND_SCHEDULE_CMD",
                 "BACKEND_HEALTH_PATH", "BACKEND_LOGIN_PATH",
                 "RUN_QUEUE", "RUN_SCHEDULER"]),
    ("apps", ["WEB_APP", "WEB_CMD",
              "RUN_ADMIN", "ADMIN_APP", "ADMIN_CMD",
              "RUN_LANDING", "LANDING_APP", "LANDING_CMD",
              "RUN_MOBILE", "MOBILE_APP", "MOBILE_CMD",
              "RUN_DESKTOP", "DESKTOP_STACK", "DESKTOP_APP", "DESKTOP_CMD",
              "DESKTOP_HOST_CMD", "EXTRA_DEPS_APPS", "EXTRA_APPS"]),
    ("infrastructure", ["DB_ENGINE", "DB_DATABASE", "DB_USERNAME", "DB_PASSWORD",
                        "RUN_MIGRATIONS", "RUN_SEEDERS", "RUN_REDIS",
                        "RUN_MAILPIT", "RUN_MINIO", "MINIO_BUCKET",
                        "MINIO_ROOT_USER", "MINIO_ROOT_PASSWORD"]),
    ("deploy", ["DEPLOY_"]),
    ("ports", ["_PORT"]),
    ("urls", ["VITE_", "EXPO_", "REACT_NATIVE_"]),
    ("docker", ["_MEMORY_LIMIT", "_CPU_LIMIT", "DOCKER_SHM_SIZE"]),
    ("other", []),
]


def rank(key):
    """(group, position) — an unlisted key joins the group its prefix or
    suffix matches, and anything left over goes in "other"."""
    for index, (_, group) in enumerate(GROUPS):
        for position, entry in enumerate(group):
            if key == entry:
                return (index, position)
            if entry.endswith("_") and key.startswith(entry):
                return (index, position)
            if entry.startswith("_") and key.endswith(entry):
                return (index, position)
    return (len(GROUPS) - 1, 0)


# An extra app's own keys belong with the apps, next to EXTRA_APPS — except
# its port, which belongs with the ports.
apps_index = next(i for i, (name, _) in enumerate(GROUPS) if name == "apps")
extra = [a.split(":")[0] for a in str(data.get("EXTRA_APPS", "")).split()]
placed = {}
for offset, app in enumerate(extra):
    prefix = re.sub(r"[^A-Z0-9]", "_", app.upper()) + "_"
    for key in data:
        if key.startswith(prefix) and not key.endswith("_PORT"):
            placed[key] = (apps_index, len(GROUPS[apps_index][1]) + offset)

out = {}
for key in sorted(data, key=lambda k: (placed.get(k) or rank(k), k)):
    if key.startswith("_"):
        # Comment keys the author added stay at the top level, where they read
        # as comments on the file rather than on one section.
        out[key] = data[key]
        continue
    index, _ = placed.get(key) or rank(key)
    out.setdefault(GROUPS[index][0], {})[key] = data[key]

with open(target, "w", encoding="utf-8") as fh:
    json.dump(out, fh, indent=2)
    fh.write("\n")
PY
}
