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

ARCHIVE_URL="https://download.sentralogic.id/scryfer-agent-linux-x64.tar.gz"
INSTALL_DIR="/opt/scryfer-agent"
CONFIG_DIR="/etc/scryfer-agent"
ENV_FILE="$CONFIG_DIR/agent.env"
RUNNER="$INSTALL_DIR/run-scryfer-agent.sh"
SUPERVISOR_CONF="/etc/supervisor/conf.d/scryfer-agent.conf"
PROGRAM_NAME="scryfer-agent"
TMP_ARCHIVE="/tmp/scryfer-agent-linux-x64.tar.gz"

say() { printf '\n==> %s\n' "$*"; }
warn() { printf '\nWARNING: %s\n' "$*" >&2; }
die() { printf '\nERROR: %s\n' "$*" >&2; exit 1; }

confirm() {
    local prompt="$1" reply
    read -r -p "$prompt [y/N]: " reply
    case "$reply" in
        y|Y|yes|YES|Yes) return 0 ;;
        *) return 1 ;;
    esac
}

require_root() {
    [[ ${EUID:-$(id -u)} -eq 0 ]] || die "Run this installer as root, for example: sudo $0"
}

install_apt_package() {
    local package="$1"
    confirm "Install missing package '$package' now?" || die "Cannot continue without $package."
    confirm "Run apt-get update before installing '$package'?" && apt-get update
    apt-get install -y "$package"
}

check_command() {
    local command_name="$1" package_name="$2"
    if command -v "$command_name" >/dev/null 2>&1; then
        say "Found $command_name at $(command -v "$command_name")"
    else
        warn "$command_name is not installed."
        install_apt_package "$package_name"
    fi
}

require_root

say "This installs only the Scryfer relay agent and Supervisor entry."
printf '%s\n' "It does not configure Nginx, DNS, a subdomain, or Certbot."
confirm "Continue with the Scryfer relay agent installation?" || exit 0

confirm "Check required commands and packages?" || die "Required dependency checks were declined."
check_command curl curl
check_command tar tar
check_command supervisorctl supervisor

if command -v dotnet >/dev/null 2>&1 && dotnet --list-runtimes 2>/dev/null | grep -q '^Microsoft.NETCore.App 10\.'; then
    say ".NET 10 runtime is installed."
else
    warn ".NET 10 runtime was not detected."
    install_apt_package dotnet-runtime-10.0
fi

confirm "Enable and start Supervisor?" && {
    systemctl enable supervisor
    systemctl start supervisor
}

DEFAULT_RELAY_URL=""
DEFAULT_AGENT_ID="$(hostname -s 2>/dev/null || hostname)"

confirm "Enter relay connection settings now?" || die "Relay URL, agent ID, and token are required."
read -r -p "Relay URL (example: https://scryfer.example.com): " RELAY_URL
[[ "$RELAY_URL" =~ ^https?:// ]] || die "Relay URL must start with http:// or https://"
read -r -p "Agent ID [$DEFAULT_AGENT_ID]: " AGENT_ID
AGENT_ID="${AGENT_ID:-$DEFAULT_AGENT_ID}"
read -r -s -p "Agent token: " AGENT_TOKEN
printf '\n'
[[ -n "$AGENT_TOKEN" ]] || die "Agent token cannot be empty."

printf '\nRelay URL : %s\nAgent ID  : %s\n' "$RELAY_URL" "$AGENT_ID"
confirm "Use these relay settings?" || die "Installation cancelled before writing settings."

confirm "Download the published agent archive from $ARCHIVE_URL?" || die "Archive download declined."
rm -f "$TMP_ARCHIVE"
curl -fL --retry 3 --connect-timeout 20 -o "$TMP_ARCHIVE" "$ARCHIVE_URL"

confirm "Validate the downloaded gzip archive?" || die "Archive validation declined."
tar -tzf "$TMP_ARCHIVE" >/dev/null

if [[ -e "$INSTALL_DIR" ]]; then
    BACKUP_DIR="${INSTALL_DIR}.backup-$(date +%Y%m%d-%H%M%S)"
    confirm "Existing installation found. Move it to $BACKUP_DIR?" || die "Existing installation was not replaced."
    mv "$INSTALL_DIR" "$BACKUP_DIR"
fi

confirm "Create installation directory $INSTALL_DIR?" || die "Installation directory creation declined."
mkdir -p "$INSTALL_DIR"

confirm "Extract the Scryfer agent into $INSTALL_DIR?" || die "Extraction declined."
tar -xzf "$TMP_ARCHIVE" -C "$INSTALL_DIR" --strip-components=1
[[ -x "$INSTALL_DIR/FileSystemShellMcp.Relay.Agent" ]] || die "Published executable is missing after extraction."

confirm "Create protected configuration directory $CONFIG_DIR?" || die "Configuration directory creation declined."
mkdir -p "$CONFIG_DIR"
chmod 700 "$CONFIG_DIR"

confirm "Write relay settings to $ENV_FILE with root-only permissions?" || die "Writing relay settings declined."
{
    printf 'Agent__RelayUrl=%q\n' "$RELAY_URL"
    printf 'Agent__AgentId=%q\n' "$AGENT_ID"
    printf 'Agent__Token=%q\n' "$AGENT_TOKEN"
} > "$ENV_FILE"
chmod 600 "$ENV_FILE"

confirm "Create the agent launcher $RUNNER?" || die "Launcher creation declined."
cat > "$RUNNER" <<'RUNNER_EOF'
#!/usr/bin/env bash
set -Eeuo pipefail
ENV_FILE="/etc/scryfer-agent/agent.env"
[[ -r "$ENV_FILE" ]] || { echo "Missing settings file: $ENV_FILE" >&2; exit 1; }
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
cd /opt/scryfer-agent
exec /opt/scryfer-agent/FileSystemShellMcp.Relay.Agent
RUNNER_EOF
chmod 750 "$RUNNER"

confirm "Create Supervisor log directory /var/log/scryfer-agent?" || die "Log directory creation declined."
mkdir -p /var/log/scryfer-agent

if [[ -f "$SUPERVISOR_CONF" ]]; then
    CONF_BACKUP="${SUPERVISOR_CONF}.backup-$(date +%Y%m%d-%H%M%S)"
    confirm "Supervisor entry already exists. Back it up to $CONF_BACKUP?" || die "Existing Supervisor entry was not replaced."
    cp -a "$SUPERVISOR_CONF" "$CONF_BACKUP"
fi

confirm "Write Supervisor entry $SUPERVISOR_CONF?" || die "Supervisor configuration creation declined."
cat > "$SUPERVISOR_CONF" <<EOF
[program:$PROGRAM_NAME]
command=$RUNNER
directory=$INSTALL_DIR
user=root
autostart=true
autorestart=true
startsecs=5
startretries=5
stopsignal=INT
stopwaitsecs=20
stopasgroup=true
killasgroup=true
stdout_logfile=/var/log/scryfer-agent/out.log
stderr_logfile=/var/log/scryfer-agent/err.log
stdout_logfile_maxbytes=10MB
stderr_logfile_maxbytes=10MB
stdout_logfile_backups=5
stderr_logfile_backups=5
EOF

confirm "Run supervisorctl reread?" && supervisorctl reread
confirm "Run supervisorctl update?" && supervisorctl update
confirm "Start or restart $PROGRAM_NAME now?" && {
    supervisorctl restart "$PROGRAM_NAME" 2>/dev/null || supervisorctl start "$PROGRAM_NAME"
}

confirm "Show final Supervisor status?" && supervisorctl status "$PROGRAM_NAME" || true
confirm "Show the latest agent error log?" && tail -n 40 /var/log/scryfer-agent/err.log 2>/dev/null || true

say "Scryfer relay agent installation flow completed."
printf '%s\n' \
    "Program: $PROGRAM_NAME" \
    "Install directory: $INSTALL_DIR" \
    "Settings: $ENV_FILE" \
    "Supervisor entry: $SUPERVISOR_CONF"
