#!/usr/bin/env bash

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd "${SCRIPT_DIR}/../.." && pwd)"
TRANSPORT_LIB="${SCRIPT_DIR}/lib/transport.sh"
DEFAULT_ENV_FILE="${SCRIPT_DIR}/enterprise.env"
DEFAULT_REMOTE_DIR="/opt/security-center/enterprise/rendered"

# shellcheck disable=SC1090
source "${TRANSPORT_LIB}"

usage() {
  cat <<'EOF'
Promote an existing Security Center user to admin by email.

This helper updates the deployed MySQL data directly on the remote host:
- adds the `admin` role in `user_roles`
- sets `users.default_role_id` to the `admin` role

Usage:
  ./scripts/enterprise/promote-enterprise-admin.sh \
    --env-file ./scripts/enterprise/enterprise.prod.env \
    --email alice@example.com \
    --instance-id i-0123456789abcdef0

Options:
  --env-file <path>        Enterprise env file. Default: scripts/enterprise/enterprise.env
  --email <email>          Required. User email to promote.
  --transport <mode>       Optional. ssm (default) or ssh.
  --instance-id <id>       Required for ssm unless provided by caller/env.
  --host <user@host>       Required for ssh.
  --identity-file <path>   Optional. SSH private key for ssh mode.
  --remote-dir <path>      Optional. Compose/rendered directory. Default: /opt/security-center/enterprise/rendered
  --region <name>          AWS region for ssm mode and SSM secret resolution.
  --profile <name>         AWS CLI profile override.
  --dry-run                Print the planned remote command without changing the remote host.
  --help                   Show this help.
EOF
}

info() { echo "INFO: $*"; }
warn() { echo "WARN: $*" >&2; }
die() { echo "ERROR: $*" >&2; exit 1; }

resolve_path() {
  local path="$1"
  if [[ "$path" = /* ]]; then
    printf '%s' "$path"
    return 0
  fi
  if [[ -e "$path" ]]; then
    printf '%s' "$path"
    return 0
  fi
  if [[ -e "${ROOT_DIR}/${path}" ]]; then
    printf '%s' "${ROOT_DIR}/${path}"
    return 0
  fi
  printf '%s' "$path"
}

trim() {
  local value="${1:-}"
  value="${value#"${value%%[![:space:]]*}"}"
  value="${value%"${value##*[![:space:]]}"}"
  printf '%s' "$value"
}

get_env_value() {
  local env_file="$1"
  local key="$2"
  [[ -f "${env_file}" ]] || return 0
  python3 - "$env_file" "$key" <<'PY'
from pathlib import Path
import sys

path = Path(sys.argv[1])
key = sys.argv[2]
for raw in path.read_text().splitlines():
    line = raw.strip()
    if not line or line.startswith("#") or "=" not in line:
        continue
    lhs, rhs = line.split("=", 1)
    if lhs.strip() == key:
        print(rhs.strip())
        break
PY
}

resolve_ssm_param() {
  local name="$1"
  local value=""
  if ! value="$(aws ssm get-parameter \
    --name "${name}" \
    --with-decryption \
    --region "${AWS_REGION_NAME}" \
    --query 'Parameter.Value' \
    --output text 2>/tmp/security-center-promote-admin-ssm-error.$$)"; then
    local error_text=""
    error_text="$(tr '\n' ' ' </tmp/security-center-promote-admin-ssm-error.$$ 2>/dev/null || true)"
    rm -f /tmp/security-center-promote-admin-ssm-error.$$
    die "failed to resolve SSM parameter ${name}: ${error_text:-unknown aws ssm error}"
  fi
  rm -f /tmp/security-center-promote-admin-ssm-error.$$
  printf '%s' "${value}"
}

sql_escape_literal() {
  local value="$1"
  value="${value//\\/\\\\}"
  value="${value//\'/\'\'}"
  printf '%s' "${value}"
}

ENV_FILE="${DEFAULT_ENV_FILE}"
EMAIL=""
TRANSPORT="ssm"
INSTANCE_ID=""
REMOTE_HOST=""
IDENTITY_FILE=""
REMOTE_DIR="${DEFAULT_REMOTE_DIR}"
AWS_REGION_NAME="${AWS_REGION:-${AWS_DEFAULT_REGION:-}}"
AWS_PROFILE_NAME="${AWS_PROFILE:-}"
DRY_RUN="false"

while (($# > 0)); do
  case "$1" in
    --env-file)
      ENV_FILE="$2"
      shift 2
      ;;
    --email)
      EMAIL="$2"
      shift 2
      ;;
    --transport)
      TRANSPORT="$2"
      shift 2
      ;;
    --instance-id)
      INSTANCE_ID="$2"
      shift 2
      ;;
    --host)
      REMOTE_HOST="$2"
      shift 2
      ;;
    --identity-file)
      IDENTITY_FILE="$(resolve_path "$2")"
      shift 2
      ;;
    --remote-dir)
      REMOTE_DIR="$2"
      shift 2
      ;;
    --region)
      AWS_REGION_NAME="$2"
      shift 2
      ;;
    --profile)
      AWS_PROFILE_NAME="$2"
      shift 2
      ;;
    --dry-run)
      DRY_RUN="true"
      shift
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    *)
      die "unknown argument: $1"
      ;;
  esac
done

ENV_FILE="$(resolve_path "${ENV_FILE}")"
[[ -f "${ENV_FILE}" ]] || die "env file not found: ${ENV_FILE}"
EMAIL="$(trim "${EMAIL}")"
[[ -n "${EMAIL}" ]] || die "--email is required"

if [[ -z "${AWS_REGION_NAME}" ]]; then
  AWS_REGION_NAME="$(trim "$(get_env_value "${ENV_FILE}" "SC_AWS_REGION")")"
fi

if [[ "${TRANSPORT}" == "ssm" && -z "${INSTANCE_ID}" ]]; then
  INSTANCE_ID="$(trim "$(get_env_value "${ENV_FILE}" "SC_EC2_INSTANCE_ID")")"
fi

case "${TRANSPORT}" in
  ssm)
    [[ -n "${INSTANCE_ID}" ]] || die "--instance-id is required for --transport ssm"
    [[ -n "${AWS_REGION_NAME}" ]] || die "--region is required for SSM secret resolution and --transport ssm"
    ;;
  ssh)
    [[ -n "${REMOTE_HOST}" ]] || die "--host is required for --transport ssh"
    [[ -n "${AWS_REGION_NAME}" ]] || die "--region is required for SSM secret resolution"
    ;;
  *)
    die "unsupported transport: ${TRANSPORT}"
    ;;
esac

SC_TRANSPORT_MODE="${TRANSPORT}"
SC_TRANSPORT_DRY_RUN="${DRY_RUN}"
SC_TRANSPORT_REMOTE_HOST="${REMOTE_HOST}"
SC_TRANSPORT_INSTANCE_ID="${INSTANCE_ID}"
SC_TRANSPORT_IDENTITY_FILE="${IDENTITY_FILE}"
SC_TRANSPORT_AWS_REGION="${AWS_REGION_NAME}"
SC_TRANSPORT_AWS_PROFILE="${AWS_PROFILE_NAME}"
sc_transport_init

export AWS_REGION="${AWS_REGION_NAME}"
export AWS_DEFAULT_REGION="${AWS_REGION_NAME}"
export AWS_SDK_LOAD_CONFIG=1
if [[ -n "${AWS_PROFILE_NAME}" ]]; then
  export AWS_PROFILE="${AWS_PROFILE_NAME}"
fi

MYSQL_ROOT_PARAM="$(trim "$(get_env_value "${ENV_FILE}" "SC_SSM_PARAM_MYSQL_ROOT_PASSWORD")")"
MYSQL_DATABASE="$(trim "$(get_env_value "${ENV_FILE}" "SC_MYSQL_DATABASE")")"
[[ -n "${MYSQL_ROOT_PARAM}" ]] || die "SC_SSM_PARAM_MYSQL_ROOT_PASSWORD is required in ${ENV_FILE}"
[[ -n "${MYSQL_DATABASE}" ]] || MYSQL_DATABASE="security_center"

NORMALIZED_EMAIL="$(python3 - "${EMAIL}" <<'PY'
import sys
print(sys.argv[1].strip().lower())
PY
)"

MYSQL_ROOT_PASSWORD="<resolved-from-ssm>"
if [[ "${DRY_RUN}" != "true" ]]; then
  MYSQL_ROOT_PASSWORD="$(resolve_ssm_param "${MYSQL_ROOT_PARAM}")"
fi

EMAIL_SQL="$(sql_escape_literal "${NORMALIZED_EMAIL}")"
printf -v REMOTE_DIR_Q '%q' "${REMOTE_DIR}"
printf -v MYSQL_DATABASE_Q '%q' "${MYSQL_DATABASE}"
printf -v MYSQL_ROOT_PASSWORD_Q '%q' "${MYSQL_ROOT_PASSWORD}"
printf -v EMAIL_DISPLAY_Q '%q' "${NORMALIZED_EMAIL}"

REMOTE_SCRIPT="set -euo pipefail
compose_dir=${REMOTE_DIR_Q}
mysql_database=${MYSQL_DATABASE_Q}
mysql_root_password=${MYSQL_ROOT_PASSWORD_Q}
target_email=${EMAIL_DISPLAY_Q}

cd \"\$compose_dir\"
[[ -f .env.runtime ]] || { echo \"ERROR: missing .env.runtime under \$compose_dir\" >&2; exit 1; }
[[ -f docker-compose.enterprise.yml ]] || { echo \"ERROR: missing docker-compose.enterprise.yml under \$compose_dir\" >&2; exit 1; }

compose_cmd=(docker compose --env-file .env.runtime -f docker-compose.enterprise.yml)

mysql_query() {
  \"\${compose_cmd[@]}\" exec -T -e MYSQL_PWD=\"\$mysql_root_password\" mysql \
    mysql -uroot -D \"\$mysql_database\" -Nse \"\$1\"
}

user_id=\"\$(mysql_query \"SELECT id FROM users WHERE LOWER(TRIM(email))='${EMAIL_SQL}' LIMIT 1;\")\"
[[ -n \"\$user_id\" ]] || { echo \"ERROR: user not found for email: \$target_email\" >&2; exit 1; }

admin_role_id=\"\$(mysql_query \"SELECT id FROM roles WHERE name='admin' LIMIT 1;\")\"
[[ -n \"\$admin_role_id\" ]] || { echo \"ERROR: admin role not found\" >&2; exit 1; }

mysql_query \"INSERT IGNORE INTO user_roles (user_id, role_id) VALUES (\${user_id}, \${admin_role_id});\" >/dev/null
mysql_query \"UPDATE users SET default_role_id=\${admin_role_id} WHERE id=\${user_id};\" >/dev/null

echo \"INFO: promoted user to admin\"
echo \"INFO:   - email: \$target_email\"
echo \"INFO:   - user id: \$user_id\"
echo \"INFO:   - admin role id: \$admin_role_id\"
echo \"INFO:   - resulting roles:\"
mysql_query \"SELECT CONCAT('  - ', r.name) FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id=\${user_id} ORDER BY r.name;\"
"

sc_transport_run "${REMOTE_SCRIPT}"
