#!/usr/bin/env bash

set -Eeuo pipefail

ACTION=${1:-}
[[ -n "$ACTION" ]] || { echo 'usage: app-runtime-control.sh enable|disable|status [--node app01|app02] [--dry-run]' >&2; exit 2; }
shift

NODE=
DRY_RUN=0
while (($#)); do
    case "$1" in
        --node) NODE=${2:-}; shift 2 ;;
        --dry-run) DRY_RUN=1; shift ;;
        *) echo "unknown argument: $1" >&2; exit 2 ;;
    esac
done

case "$ACTION" in
    enable|disable|status) ;;
    *) echo "unknown action: $ACTION" >&2; exit 2 ;;
esac

if [[ -r /etc/zhct/node.env ]]; then
    # shellcheck disable=SC1091
    source /etc/zhct/node.env
    [[ "${ROLE:-}" == app ]] || { echo 'node identity is not an app role' >&2; exit 1; }
    if [[ -n "$NODE" && "$NODE" != "${NODE_KEY:-}" ]]; then
        echo "requested node $NODE does not match identity ${NODE_KEY:-missing}" >&2
        exit 1
    fi
    NODE=${NODE_KEY:-}
fi
[[ "$NODE" == app01 || "$NODE" == app02 ]] || { echo 'node must be app01 or app02' >&2; exit 2; }

if [[ "$DRY_RUN" == 1 ]]; then
    printf 'would %s Supervisor/crond for %s through release, singleton, file, Redis5 and MQTT gates\n' "$ACTION" "$NODE"
    exit 0
fi
[[ $(id -u) -eq 0 ]] || { echo 'live runtime control requires root' >&2; exit 1; }

supervisor_status() {
    /usr/local/bin/supervisorctl -c /etc/supervisord.conf status
}

assert_supervisor_running() {
    local output count
    output=$(supervisor_status)
    count=$(awk 'NF {count++} END {print count+0}' <<<"$output")
    [[ "$count" -eq 9 ]] || { printf '%s\n' "$output" >&2; echo "expected 9 Supervisor processes, got $count" >&2; return 1; }
    awk 'NF && $2 != "RUNNING" {bad=1} END {exit bad}' <<<"$output" || {
        printf '%s\n' "$output" >&2
        echo 'one or more Supervisor processes are not RUNNING' >&2
        return 1
    }
}

wait_for_supervisor() {
    local attempt
    for attempt in {1..15}; do
        if assert_supervisor_running >/dev/null 2>&1; then
            return 0
        fi
        sleep 2
    done
    assert_supervisor_running
}

case "$ACTION" in
    disable)
        systemctl disable --now crond.service supervisor.service
        ! systemctl is-active --quiet crond.service
        ! systemctl is-active --quiet supervisor.service
        echo "PASS: $NODE Supervisor/crond disabled"
        ;;
    status)
        systemctl is-enabled --quiet supervisor.service
        systemctl is-active --quiet supervisor.service
        systemctl is-enabled --quiet crond.service
        systemctl is-active --quiet crond.service
        assert_supervisor_running
        echo "PASS: $NODE Supervisor=9 RUNNING and crond active"
        ;;
    enable)
        [[ -f /workspace/wwwroot/zhct_sanquan/project/think ]] || { echo 'Store release is missing think' >&2; exit 1; }
        [[ -f /workspace/wwwroot/aizhct_sanquan/project/think ]] || { echo 'AI release is missing think' >&2; exit 1; }
        systemctl is-active --quiet nginx.service
        systemctl is-active --quiet php-fpm73.service
        systemctl is-active --quiet php-fpm74.service
        /usr/local/sbin/singleton-state-check.sh --node "$NODE" --config /etc/supervisor/conf.d/sanquan.conf --cron /etc/cron.d/zhct-sanquan
        /usr/local/sbin/apply-file-role-policy.sh --node "$NODE"
        /usr/local/sbin/redis-runtime-check.sh
        /usr/local/sbin/mqtt-runtime-check.sh
        python3 -c 'from supervisor.options import ServerOptions; ServerOptions().realize(["-c", "/etc/supervisord.conf"], doc="Supervisor configuration validation")'
        systemctl enable --now supervisor.service
        if ! wait_for_supervisor; then
            systemctl disable --now supervisor.service
            exit 1
        fi
        if ! systemctl enable --now crond.service || ! systemctl is-active --quiet crond.service; then
            systemctl disable --now crond.service supervisor.service
            exit 1
        fi
        assert_supervisor_running
        echo "PASS: $NODE Q-263 runtime gates passed; Supervisor=9 RUNNING and crond active"
        ;;
esac
