#!/usr/bin/env bash

set -Eeuo pipefail

usage() {
    echo "Usage: $0 <app01|app02> <run_id> <--dry-run|--execute|--rollback>" >&2
    exit 2
}

[[ $# -eq 3 ]] || usage
NODE_KEY=$1
RUN_ID=$2
MODE=$3

case "$NODE_KEY" in
    app01) QID=q111; EXPECTED_HOST=sqjcapp01; EXPECTED_IP=10.2.203.104 ;;
    app02) QID=q112; EXPECTED_HOST=sqjcapp02; EXPECTED_IP=10.2.203.105 ;;
    *) usage ;;
esac
[[ "$RUN_ID" =~ ^${QID}-[A-Za-z0-9+_.:-]+$ ]] || {
    echo "ERROR: run_id must begin with ${QID}-" >&2
    exit 2
}
case "$MODE" in --dry-run|--execute|--rollback) ;; *) usage ;; esac
[[ $(id -u) -eq 0 ]] || { echo 'ERROR: root required' >&2; exit 1; }
[[ $(hostname -s) == "$EXPECTED_HOST" ]] || { echo 'ERROR: hostname mismatch' >&2; exit 1; }
ip -o -4 addr show scope global | grep -Eq "(^|[[:space:]])${EXPECTED_IP//./\\.}/" || {
    echo 'ERROR: expected IPv4 missing' >&2
    exit 1
}

EVIDENCE_ROOT="/var/backups/zhct-${QID}/evidence"
EVIDENCE_DIR="$EVIDENCE_ROOT/$RUN_ID"
BACKUP_ROOT="/var/backups/zhct-${QID}/files"
[[ ! -e "$EVIDENCE_DIR" && ! -L "$EVIDENCE_DIR" ]] || {
    echo "ERROR: evidence directory already exists: $EVIDENCE_DIR" >&2
    exit 1
}
install -d -m 0700 -o root -g root "$EVIDENCE_DIR"
exec > >(tee "$EVIDENCE_DIR/execution.log") 2>&1

finish() {
    rc=$?
    trap - EXIT
    set +e
    {
        echo "qid=$QID"
        echo "run_id=$RUN_ID"
        echo "node_key=$NODE_KEY"
        echo "mode=$MODE"
        echo "exit_code=$rc"
        if [[ $rc -eq 0 ]]; then echo "result=PASS"; else echo "result=FAIL"; fi
    } >"$EVIDENCE_DIR/result.env"
    chmod 0600 "$EVIDENCE_DIR/result.env"
    echo "APP_ACTIVATE_EXIT_CODE=$rc"
    if [[ $rc -eq 0 ]]; then echo APP_ACTIVATE_RESULT=PASS; else echo APP_ACTIVATE_RESULT=FAIL; fi
    echo APP_ACTIVATE_END
    exit "$rc"
}
trap finish EXIT

echo APP_ACTIVATE_BEGIN
date '+%Y-%m-%dT%H:%M:%S%z'
echo "QID=$QID NODE_KEY=$NODE_KEY EXPECTED_HOST=$EXPECTED_HOST EXPECTED_IP=$EXPECTED_IP MODE=$MODE"

echo "e637ca657a897c6d0b689bbd6347f04516baf5c9f32350cd1e8a2071c211a0a5  /opt/zhct-deploy/common/scripts/activate-role.sh" | sha256sum -c -
echo "e3eae16aa5c87f43b56495fc71de378a947578cabe18b507e8fed01ac1f32025  /opt/zhct-deploy/common/bin/role-action.sh" | sha256sum -c -
echo "03c6b13a0def5bf3954e069581b6f9fbe0f81f24285ba2319b6279c0406d70aa  /opt/zhct-deploy/roles/app/hooks.sh" | sha256sum -c -
echo "d43e179c108f6db551b452256f867d6d4f6fc9e031c1d4def2f343966af8d684  /opt/zhct-deploy/roles/app/manifests/systemd-units.tsv" | sha256sum -c -

grep -Fxq 'ROLE=app' /etc/zhct/node.env
grep -Fxq "NODE_KEY=$NODE_KEY" /etc/zhct/node.env
grep -Fxq "NODE_IP=$EXPECTED_IP" /etc/zhct/node.env
grep -Fxq "NODE_NAME=$EXPECTED_HOST" /etc/zhct/node.env
[[ -s /etc/machine-id ]]
[[ -s /etc/ssh/ssh_host_ed25519_key ]]

disable_all() {
    systemctl disable --now \
        nginx.service php-fpm73.service php-fpm74.service \
        supervisor.service crond.service
    systemctl reset-failed \
        nginx.service php-fpm73.service php-fpm74.service \
        supervisor.service crond.service || true
}

if [[ "$MODE" == --rollback ]]; then
    disable_all
else
    for unit in nginx.service php-fpm73.service php-fpm74.service supervisor.service crond.service; do
        [[ $(systemctl is-enabled "$unit" 2>/dev/null || true) == disabled ]]
        [[ $(systemctl is-active "$unit" 2>/dev/null || true) == inactive ]]
    done
    ! ss -H -lntup | grep -Eq ':(8081|18081)([[:space:]]|$)'
    ! pgrep -x supervisord
    ! pgrep -x crond
    ! pgrep -x php

    args=(--role app --bundle-root /opt/zhct-deploy)
    if [[ "$MODE" == --dry-run ]]; then args+=(--dry-run); fi
    env RUN_ID="$RUN_ID" BACKUP_ROOT="$BACKUP_ROOT" \
        /opt/zhct-deploy/common/scripts/activate-role.sh "${args[@]}"
fi

if [[ "$MODE" == --execute ]]; then
    for unit in php-fpm73.service php-fpm74.service nginx.service; do
        enabled=$(systemctl is-enabled "$unit" 2>/dev/null || true)
        active=$(systemctl is-active "$unit" 2>/dev/null || true)
        echo "$unit enabled=$enabled active=$active"
        [[ "$enabled" == enabled && "$active" == active ]]
    done
    for unit in supervisor.service crond.service; do
        enabled=$(systemctl is-enabled "$unit" 2>/dev/null || true)
        active=$(systemctl is-active "$unit" 2>/dev/null || true)
        echo "$unit enabled=$enabled active=$active"
        [[ "$enabled" == disabled && "$active" == inactive ]]
    done
    ss -H -ltn | awk '$4 ~ /:8081$/ {found=1} END {exit !found}'
    ss -H -ltn | awk '$4 ~ /^127\\.0\\.0\\.1:18081$/ {found=1} END {exit !found}'
    ! pgrep -x supervisord
    ! pgrep -x crond
    ! pgrep -x php
elif [[ "$MODE" == --dry-run ]]; then
    for unit in nginx.service php-fpm73.service php-fpm74.service supervisor.service crond.service; do
        enabled=$(systemctl is-enabled "$unit" 2>/dev/null || true)
        active=$(systemctl is-active "$unit" 2>/dev/null || true)
        echo "$unit enabled=$enabled active=$active"
        [[ "$enabled" == disabled && "$active" == inactive ]]
    done
    ! ss -H -lntup | grep -Eq ':(8081|18081)([[:space:]]|$)'
else
    for unit in nginx.service php-fpm73.service php-fpm74.service supervisor.service crond.service; do
        enabled=$(systemctl is-enabled "$unit" 2>/dev/null || true)
        active=$(systemctl is-active "$unit" 2>/dev/null || true)
        echo "$unit enabled=$enabled active=$active"
        [[ "$enabled" == disabled && "$active" == inactive ]]
    done
    ! ss -H -lntup | grep -Eq ':(8081|18081)([[:space:]]|$)'
    ! pgrep -x nginx
    ! pgrep -x php-fpm
    ! pgrep -x supervisord
    ! pgrep -x crond
    ! pgrep -x php
fi

echo APP_ACTIVATE_EVIDENCE_DIR="$EVIDENCE_DIR"
