#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# shellcheck source=/dev/null
source "$SCRIPT_DIR/libenv.sh"

ENV_FILE=$(limristem_mail_resolve_main_env_file)

usage() {
  cat <<'EOF'
Usage:
  manage-topology.sh show [--json]
  manage-topology.sh apply-mode <standalone|routed|cluster> [options]

Options:
  --server-id ID
  --routed-db shared|synced
  --storage nfs|ceph|s3
  --storage-path PATH
  --s3-cache-ttl SECONDS
  --s3-cache-max-mb MB
  --internode-token TOKEN

Modes:
  standalone  Single-node classic install
  routed      Routed Mesh (split-domain multi-backend)
  cluster     Storage Cluster (shared NFS/Ceph/S3 mail storage)
EOF
}

require_root() {
  if [[ $EUID -ne 0 ]]; then
    echo "Run as root." >&2
    exit 1
  fi
}

load_env() {
  limristem_mail_load_env_file "$ENV_FILE"
}

show() {
  load_env
  local mode=${LIMRISTEM_MAIL_TOPOLOGY_MODE:-standalone}
  local sid=${LIMRISTEM_MAIL_SERVER_ID:-}
  local strategy=${LIMRISTEM_MAIL_ROUTED_DB_STRATEGY:-shared}
  local storage=${LIMRISTEM_MAIL_CLUSTER_STORAGE:-nfs}
  if [[ ${1:-} == "--json" ]]; then
    python3 - "$mode" "$sid" "$strategy" "$storage" <<'PY'
import json, sys
print(json.dumps({
  "mode": sys.argv[1],
  "server_id": sys.argv[2] or None,
  "routed_db_strategy": sys.argv[3],
  "cluster_storage": sys.argv[4],
}))
PY
    return
  fi
  printf 'mode=%s\n' "$mode"
  printf 'server_id=%s\n' "$sid"
  printf 'routed_db_strategy=%s\n' "$strategy"
  printf 'cluster_storage=%s\n' "$storage"
}

write_transport_stub() {
  # Postfix transport map for routed mode (filled by sync-transport-maps).
  local mapf=/etc/postfix/limristem-transport
  if [[ ! -f "$mapf" ]]; then
    printf '# limristem routed transport map\n' > "$mapf"
    postmap "$mapf" 2>/dev/null || true
  fi
  if command -v postconf >/dev/null 2>&1; then
    if [[ "${LIMRISTEM_MAIL_TOPOLOGY_MODE:-standalone}" == "routed" ]]; then
      postconf -e 'transport_maps = hash:/etc/postfix/limristem-transport'
    else
      postconf -X transport_maps 2>/dev/null || true
    fi
    systemctl reload postfix >/dev/null 2>&1 || true
  fi
}

apply_mode() {
  local mode=$1
  shift
  local server_id="" routed_db="shared" storage="nfs" storage_path="" s3_ttl="3600" s3_max="10240" token=""
  while (( $# > 0 )); do
    case "$1" in
      --server-id) server_id=$2; shift 2 ;;
      --routed-db) routed_db=$2; shift 2 ;;
      --storage) storage=$2; shift 2 ;;
      --storage-path) storage_path=$2; shift 2 ;;
      --s3-cache-ttl) s3_ttl=$2; shift 2 ;;
      --s3-cache-max-mb) s3_max=$2; shift 2 ;;
      --internode-token) token=$2; shift 2 ;;
      *) echo "Unknown option: $1" >&2; exit 1 ;;
    esac
  done
  case "$mode" in
    standalone|routed|cluster) ;;
    *) echo "Invalid mode" >&2; exit 1 ;;
  esac
  limristem_mail_upsert_env_value "$ENV_FILE" LIMRISTEM_MAIL_TOPOLOGY_MODE "$mode"
  if [[ -n "$server_id" ]]; then
    limristem_mail_upsert_env_value "$ENV_FILE" LIMRISTEM_MAIL_SERVER_ID "$server_id"
  fi
  if [[ "$mode" == "routed" ]]; then
    limristem_mail_upsert_env_value "$ENV_FILE" LIMRISTEM_MAIL_ROUTED_DB_STRATEGY "$routed_db"
  fi
  if [[ "$mode" == "cluster" ]]; then
    limristem_mail_upsert_env_value "$ENV_FILE" LIMRISTEM_MAIL_CLUSTER_STORAGE "$storage"
    [[ -n "$storage_path" ]] && limristem_mail_upsert_env_value "$ENV_FILE" LIMRISTEM_MAIL_CLUSTER_STORAGE_PATH "$storage_path"
    limristem_mail_upsert_env_value "$ENV_FILE" LIMRISTEM_MAIL_S3_CACHE_TTL_SECONDS "$s3_ttl"
    limristem_mail_upsert_env_value "$ENV_FILE" LIMRISTEM_MAIL_S3_CACHE_MAX_MB "$s3_max"
  fi
  if [[ -n "$token" ]]; then
    limristem_mail_upsert_env_value "$ENV_FILE" LIMRISTEM_MAIL_INTERNODE_TOKEN "$token"
    chmod 600 "$ENV_FILE" || true
  fi
  load_env
  write_transport_stub
  systemctl restart --no-block limristem-mail >/dev/null 2>&1 || true
  show --json
}

require_root
cmd=${1:-}
case "$cmd" in
  show) shift; show "${1:-}" ;;
  apply-mode)
    shift
    mode=${1:?mode required}
    shift
    apply_mode "$mode" "$@"
    ;;
  *) usage >&2; exit 1 ;;
esac
