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

log_file="/var/log/rizoma-installer.log"
mkdir -p "$(dirname "$log_file")"
touch "$log_file"
exec > >(tee -a "$log_file") 2>&1

if [ "$(id -u)" -ne 0 ]; then
  echo "run as root"
  exit 1
fi

echo ""
echo "  ╔══════════════════════════════════════╗"
echo "  ║       Rizoma Platform Installer      ║"
echo "  ╚══════════════════════════════════════╝"
echo ""

prompt_value() {
  local label="$1"
  local current="$2"
  local fallback="$3"
  local value=""
  if [ -n "$current" ]; then
    echo "$current"
    return
  fi
  read -r -p "$label" value < /dev/tty
  if [ -z "$value" ]; then
    value="$fallback"
  fi
  echo "$value"
}

repo_url="${RIZOMA_REPO_URL:-https://repo.rizomasec.ru}"
channel="${RIZOMA_CHANNEL:-stable}"
domain="$(prompt_value "Platform subdomain (e.g., mesh.example.com): " "${RIZOMA_DOMAIN:-}" "")"
admin_email="$(prompt_value "Admin email: " "${RIZOMA_ADMIN_EMAIL:-}" "")"
admin_name="$(prompt_value "Admin name: " "${RIZOMA_ADMIN_NAME:-}" "")"

# Password with confirmation
if [ -n "${RIZOMA_ADMIN_PASSWORD:-}" ]; then
  admin_password="${RIZOMA_ADMIN_PASSWORD}"
else
  while true; do
    read -r -s -p "Admin password (min 8 chars): " admin_password < /dev/tty
    echo
    read -r -s -p "Confirm password: " admin_password_confirm < /dev/tty
    echo
    if [ "$admin_password" != "$admin_password_confirm" ]; then
      echo "  Passwords do not match. Try again."
      continue
    fi
    if [ "${#admin_password}" -lt 8 ]; then
      echo "  Password must be at least 8 characters. Try again."
      continue
    fi
    break
  done
fi

acme_email="$admin_email"

# --- Validate inputs ---
if [ -z "$domain" ]; then
  echo "ERROR: domain is required"; exit 1
fi
if [ -z "$admin_email" ] || [ -z "$admin_name" ] || [ -z "$admin_password" ]; then
  echo "ERROR: admin credentials are required"; exit 1
fi
if ! echo "$admin_email" | grep -qE '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'; then
  echo "ERROR: admin email format is invalid"; exit 1
fi

# --- Detect package manager ---
pkg_manager=""
if command -v apt-get >/dev/null 2>&1; then
  pkg_manager="apt"
elif command -v dnf >/dev/null 2>&1; then
  pkg_manager="dnf"
elif command -v yum >/dev/null 2>&1; then
  pkg_manager="yum"
else
  echo "ERROR: no supported package manager (apt/dnf/yum)"; exit 1
fi

# --- Validate DNS ---
echo "[1/7] Validating DNS..."
public_ip="$(curl -fsS https://api.ipify.org)"
dns_ips="$(getent ahosts "$domain" | awk '{print $1}' | sort -u)"
if ! echo "$dns_ips" | grep -qx "$public_ip"; then
  echo "ERROR: DNS for $domain does not resolve to $public_ip"
  echo "  Resolved: $dns_ips"
  echo "  Expected: $public_ip"
  exit 1
fi
echo "  DNS OK: $domain -> $public_ip"

# --- Install Caddy ---
echo "[2/7] Installing Caddy..."
if ! command -v caddy >/dev/null 2>&1; then
  if [ "$pkg_manager" = "apt" ]; then
    apt-get update -qq
    apt-get install -y -qq debian-keyring debian-archive-keyring apt-transport-https curl gnupg
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
      | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg 2>/dev/null
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
      | tee /etc/apt/sources.list.d/caddy-stable.list >/dev/null
    apt-get update -qq
    apt-get install -y -qq caddy
  else
    dnf -y install caddy 2>/dev/null || yum -y install caddy 2>/dev/null || {
      echo "ERROR: could not install caddy"; exit 1
    }
  fi
fi
systemctl stop caddy >/dev/null 2>&1 || true
echo "  Caddy installed"

# --- Install Rizoma packages ---
echo "[3/7] Installing Rizoma packages..."
gpg_key_url="${RIZOMA_GPG_KEY_URL:-$repo_url/keys/rizoma.gpg}"

# Stop services if running from a previous install
systemctl stop rizoma-dashboard >/dev/null 2>&1 || true
systemctl stop rizoma-coordinator >/dev/null 2>&1 || true
systemctl stop rizoma-relay >/dev/null 2>&1 || true
systemctl stop rizoma-ingress >/dev/null 2>&1 || true

if [ "$pkg_manager" = "apt" ]; then
  apt-get install -y -qq curl ca-certificates gnupg jq openssl postgresql
  mkdir -p /usr/share/keyrings
  curl -fsS "$gpg_key_url" -o /usr/share/keyrings/rizoma.gpg 2>/dev/null
  echo "deb [signed-by=/usr/share/keyrings/rizoma.gpg trusted=yes] $repo_url/apt/$channel ./" > /etc/apt/sources.list.d/rizoma.list
  apt-get update -qq
  apt-get install -y rizoma-coordinator rizoma-dashboard rizoma-relay
else
  dnf -y install curl ca-certificates jq openssl postgresql-server postgresql 2>/dev/null || \
  yum -y install curl ca-certificates jq openssl postgresql-server postgresql
  # DNF/YUM repo setup would go here for RPM
fi
echo "  Packages installed"

# --- Setup PostgreSQL ---
echo "[4/7] Setting up PostgreSQL..."
if command -v postgresql-setup >/dev/null 2>&1; then
  postgresql-setup --initdb 2>/dev/null || true
fi
systemctl enable --now postgresql

db_user="${RIZOMA_DB_USER:-rizoma_app}"
db_name="${RIZOMA_DB_NAME:-rizoma_coordinator}"
db_password="${RIZOMA_DB_PASSWORD:-$(openssl rand -hex 24)}"
db_url="postgres://$db_user:$db_password@127.0.0.1:5432/$db_name?sslmode=disable"

if [ -f /etc/rizoma/coordinator.env ]; then
  existing_db_url="$(grep -E '^RIZOMA_COORDINATOR_DB_URL=' /etc/rizoma/coordinator.env | sed 's/^RIZOMA_COORDINATOR_DB_URL=//' || true)"
  if [ -n "$existing_db_url" ]; then
    db_url="$existing_db_url"
  fi
fi

if [ "$db_url" = "postgres://$db_user:$db_password@127.0.0.1:5432/$db_name?sslmode=disable" ]; then
  if ! sudo -u postgres psql -tAc "select 1 from pg_roles where rolname='$db_user'" | grep -q 1; then
    sudo -u postgres psql -c "create user $db_user with password '$db_password';"
  fi
  if ! sudo -u postgres psql -tAc "select 1 from pg_database where datname='$db_name'" | grep -q 1; then
    sudo -u postgres psql -c "create database $db_name owner $db_user;"
  fi
fi
echo "  PostgreSQL ready"

# --- Configure and start services ---
echo "[5/7] Configuring services..."
mkdir -p /etc/rizoma /var/lib/rizoma
chmod 700 /etc/rizoma

api_token="${RIZOMA_COORDINATOR_API_TOKEN:-$(openssl rand -hex 32)}"

# Coordinator — listens on localhost, no TLS (Caddy terminates TLS)
cat > /etc/rizoma/coordinator.env <<EOF
RIZOMA_COORDINATOR_LISTEN=127.0.0.1:8443
RIZOMA_COORDINATOR_DB_URL=$db_url
RIZOMA_COORDINATOR_API_TOKEN=$api_token
RIZOMA_COORDINATOR_INSECURE_HTTP=true
RIZOMA_COORDINATOR_RELAYS=$domain:4243
EOF

# Dashboard — listens on localhost, no TLS
cat > /etc/rizoma/dashboard.env <<EOF
RIZOMA_DASHBOARD_LISTEN=127.0.0.1:8080
RIZOMA_DASHBOARD_COORDINATOR_URL=http://127.0.0.1:8443
RIZOMA_DASHBOARD_API_TOKEN=$api_token
RIZOMA_DASHBOARD_INSECURE_HTTP=true
EOF

# Start coordinator first
systemctl enable --now rizoma-coordinator

# Wait for coordinator to be ready
echo "  Waiting for coordinator..."
for i in $(seq 1 30); do
  if curl -fsS --max-time 3 "http://127.0.0.1:8443/healthz" >/dev/null 2>&1; then
    echo "  Coordinator ready"
    break
  fi
  sleep 2
done

# Relay — issue mesh cert from coordinator for QUIC mutual TLS
echo "  Issuing relay mesh certificate..."
relay_certs=""
for i in $(seq 1 5); do
  relay_certs="$(curl -fsS -H "Authorization: Bearer $api_token" -H "Content-Type: application/json" \
    -d '{"name":"relay","ip":""}' \
    "http://127.0.0.1:8443/v1/mesh-ca" -X POST 2>/dev/null || echo "")"
  if [ -n "$relay_certs" ] && echo "$relay_certs" | jq -e '.ca_cert' >/dev/null 2>&1; then
    break
  fi
  sleep 2
done

if [ -n "$relay_certs" ] && echo "$relay_certs" | jq -e '.ca_cert' >/dev/null 2>&1; then
  echo "$relay_certs" | jq -r '.ca_cert' > /etc/rizoma/mesh_ca.pem
  echo "$relay_certs" | jq -r '.cert' > /etc/rizoma/relay_cert.pem
  echo "$relay_certs" | jq -r '.key' > /etc/rizoma/relay_key.pem
  chmod 600 /etc/rizoma/mesh_ca.pem /etc/rizoma/relay_cert.pem /etc/rizoma/relay_key.pem

  cat > /etc/rizoma/relay.env <<EOF
RIZOMA_RELAY_LISTEN=127.0.0.1:8082
RIZOMA_RELAY_INSECURE_HTTP=true
RIZOMA_RELAY_COORDINATOR_URL=http://127.0.0.1:8443
RIZOMA_RELAY_API_TOKEN=$api_token
RIZOMA_RELAY_MESH_CA_CERT=/etc/rizoma/mesh_ca.pem
RIZOMA_RELAY_MESH_CERT=/etc/rizoma/relay_cert.pem
RIZOMA_RELAY_MESH_KEY=/etc/rizoma/relay_key.pem
EOF
  echo "  Relay configured with mesh CA certificates"
else
  echo "  ERROR: Could not issue relay cert. Relay QUIC will not start."
  echo "  Check coordinator logs: journalctl -u rizoma-coordinator"
  cat > /etc/rizoma/relay.env <<EOF
RIZOMA_RELAY_LISTEN=127.0.0.1:8082
RIZOMA_RELAY_INSECURE_HTTP=true
EOF
fi

systemctl enable --now rizoma-dashboard
systemctl enable --now rizoma-relay
echo "  Services started"

# --- Configure Caddy ---
echo "[6/7] Configuring Caddy..."
cat > /etc/caddy/Caddyfile <<CADDYEOF
$domain {
    # Dashboard
    reverse_proxy /api/* http://127.0.0.1:8080
    reverse_proxy /assets/* http://127.0.0.1:8080
    reverse_proxy /app.js http://127.0.0.1:8080
    reverse_proxy /install/* http://127.0.0.1:8080
    reverse_proxy /healthz http://127.0.0.1:8080
    reverse_proxy /readyz http://127.0.0.1:8080
    reverse_proxy /info http://127.0.0.1:8080
    reverse_proxy /metrics http://127.0.0.1:8080

    # Coordinator API
    reverse_proxy /v1/* http://127.0.0.1:8443

    # Dashboard pages (catch-all)
    reverse_proxy http://127.0.0.1:8080

    tls $acme_email
}
CADDYEOF

systemctl enable --now caddy

# Wait for Caddy TLS
echo "  Waiting for TLS certificate..."
for i in $(seq 1 60); do
  if curl -fsS --max-time 3 "https://$domain/healthz" >/dev/null 2>&1; then
    echo "  TLS ready"
    break
  fi
  sleep 2
done

# --- Create admin user ---
echo "[7/7] Creating admin account..."

# Wait for coordinator
for i in $(seq 1 20); do
  if curl -fsS --max-time 3 "http://127.0.0.1:8443/healthz" >/dev/null 2>&1; then
    break
  fi
  sleep 2
done

roles="$(curl -fsS -H "Authorization: Bearer $api_token" "http://127.0.0.1:8443/v1/roles" 2>/dev/null || echo "[]")"
admin_role_id="$(echo "$roles" | jq -r '.[] | select((.name|ascii_downcase)=="admin") | .id' 2>/dev/null | head -n1)"
if [ -z "$admin_role_id" ]; then
  admin_role_id="$(curl -fsS -H "Authorization: Bearer $api_token" -H "Content-Type: application/json" \
    -d "{\"name\":\"Admin\",\"description\":\"Full access\",\"permissions\":[\"admin\"]}" \
    "http://127.0.0.1:8443/v1/roles" 2>/dev/null | jq -r '.id')"
fi

existing_user="$(curl -fsS -H "Authorization: Bearer $api_token" "http://127.0.0.1:8443/v1/users" 2>/dev/null \
  | jq -r ".[] | select(.email==\"$admin_email\") | .id" | head -n1)"
if [ -z "$existing_user" ]; then
  curl -fsS -H "Authorization: Bearer $api_token" -H "Content-Type: application/json" \
    -d "{\"email\":\"$admin_email\",\"name\":\"$admin_name\",\"role_ids\":[\"$admin_role_id\"],\"team_ids\":[],\"disabled\":false,\"password\":\"$admin_password\",\"must_change_password\":true}" \
    "http://127.0.0.1:8443/v1/users" >/dev/null 2>&1
fi
echo "  Admin account created"

echo ""
echo "  ╔══════════════════════════════════════╗"
echo "  ║     Rizoma Platform Installed        ║"
echo "  ╚══════════════════════════════════════╝"
echo ""
echo "  Dashboard:   https://$domain/"
echo "  Admin email: $admin_email"
echo "  API token:   $api_token"
echo ""
echo "  Save the API token for automation."
echo "  On first login you will be asked to change your password."
echo ""
echo "  Log: $log_file"
echo ""
