#!/usr/bin/env bash
set -Eeuo pipefail
set +x
umask 077

readonly LABEL=REDIS01_Q200_ALLOW_REDIS02_REPLICATION_PORTS
readonly EXPECTED_HOST=sqjcredis01
readonly EXPECTED_IP=10.2.203.112
readonly SOURCE_IP=10.2.203.113
readonly DIAG_AUDIT=/var/backups/zhct-q200-redis-ingress-diagnosis/q200-redis-ingress-diagnosis-20260806T023311Z/operator.log
RUN_ID="q200-redis-firewall-$(date -u +%Y%m%dT%H%M%SZ)"
AUDIT_DIR="/var/backups/zhct-q200-redis-firewall/${RUN_ID}"
AUDIT_LOG="${AUDIT_DIR}/operator.log"
zone=''
declare -a added_rules=()

rule_for() { printf 'rule family="ipv4" source address="%s/32" port port="%s" protocol="tcp" accept' "$SOURCE_IP" "$1"; }

rollback() {
    local rule
    set +e
    for rule in "${added_rules[@]}"; do
        firewall-cmd --permanent --zone="$zone" --remove-rich-rule="$rule" >/dev/null 2>&1 || true
    done
    if ((${#added_rules[@]})); then firewall-cmd --reload >/dev/null 2>&1 || true; fi
}

finish() {
    local rc=$?
    set +e
    if [[ "$rc" -eq 0 ]]; then
        printf '%s\n' 'Q200_REDIS01_FIREWALL_REMEDIATION=PASS_MINIMAL_SOURCE_SCOPED'
        printf '%s\n' 'Q200_FIREWALL_ROLLBACK=NOT_REQUIRED'
    else
        rollback
        printf '%s\n' 'Q200_REDIS01_FIREWALL_REMEDIATION=FAIL_ROLLED_BACK'
    fi
    printf '%s\n' \
        'REDIS_SERVICE_MUTATION=ZERO' \
        'SENTINEL_ORCHESTRATOR_VIP_MUTATION=ZERO' \
        "END|${LABEL}|RC=${rc}|AUDIT_LOG=${AUDIT_LOG}"
    exit "$rc"
}
trap finish EXIT

printf 'BEGIN|%s|%s\n' "$LABEL" "$(date '+%Y-%m-%dT%H:%M:%S%z')"
[[ $# -eq 0 && $(id -u) -eq 0 ]]
actual_host=$(hostname -s)
[[ "$actual_host" == "$EXPECTED_HOST" ]]
ip -o -4 addr show scope global | awk '{split($4,a,"/"); print a[1]}' | grep -Fxq "$EXPECTED_IP"
printf 'Q200_FIREWALL_TARGET_IDENTITY=PASS|host=%s|ip=%s\n' "$actual_host" "$EXPECTED_IP"

for command_name in firewall-cmd systemctl ip ss install tee grep awk; do command -v "$command_name" >/dev/null; done
[[ "$(systemctl is-active firewalld.service 2>/dev/null || true)" == active ]]
[[ -f "$DIAG_AUDIT" && ! -L "$DIAG_AUDIT" ]]
grep -Fq 'Q200_REDIS01_LOCAL_ENDPOINT_GATE=PASS|ports=6379,6387' "$DIAG_AUDIT"
grep -Fq 'FIREWALL_ROUTE_MUTATION=ZERO' "$DIAG_AUDIT"

for unit in redis5.service redis7.service; do
    [[ "$(systemctl is-enabled "$unit")" == enabled ]]
    [[ "$(systemctl is-active "$unit")" == active ]]
done
for unit in sentinel5.service sentinel7.service orchestrator.service; do
    [[ "$(systemctl is-enabled "$unit" 2>/dev/null || true)" == disabled ]]
    [[ "$(systemctl is-active "$unit" 2>/dev/null || true)" == inactive ]]
done
for port in 6379 6387; do ss -lntH "sport = :${port}" | grep -q .; done

iface=$(ip -o -4 addr show scope global | awk -v ip="$EXPECTED_IP" '{split($4,a,"/"); if(a[1]==ip){print $2; exit}}')
[[ -n "$iface" ]]
zone=$(firewall-cmd --get-zone-of-interface="$iface" 2>/dev/null || true)
if [[ -z "$zone" || "$zone" == no\ zone ]]; then zone=$(firewall-cmd --get-default-zone); fi
[[ -n "$zone" ]]
printf 'Q200_FIREWALL_PREWRITE_GATE=PASS|zone=%s|interface=%s|source=%s|ports=6379,6387\n' "$zone" "$iface" "$SOURCE_IP"

install -d -o root -g root -m 0700 "$AUDIT_DIR"
exec > >(tee -a "$AUDIT_LOG") 2>&1
printf 'AUDIT_BEGIN|%s|%s\n' "$LABEL" "$(date '+%Y-%m-%dT%H:%M:%S%z')"

for port in 6379 6387; do
    rule=$(rule_for "$port")
    if firewall-cmd --permanent --zone="$zone" --query-rich-rule="$rule" >/dev/null; then
        printf 'RULE|KEEP_EXISTING|zone=%s|source=%s|port=%s/tcp\n' "$zone" "$SOURCE_IP" "$port"
    else
        firewall-cmd --permanent --zone="$zone" --add-rich-rule="$rule"
        added_rules+=("$rule")
        printf 'RULE|ADDED|zone=%s|source=%s|port=%s/tcp\n' "$zone" "$SOURCE_IP" "$port"
    fi
done
firewall-cmd --reload

for port in 6379 6387; do
    rule=$(rule_for "$port")
    firewall-cmd --permanent --zone="$zone" --query-rich-rule="$rule" >/dev/null
    firewall-cmd --zone="$zone" --query-rich-rule="$rule" >/dev/null
    printf 'RULE_VERIFY|PASS|zone=%s|source=%s|port=%s/tcp\n' "$zone" "$SOURCE_IP" "$port"
done

for unit in redis5.service redis7.service; do
    [[ "$(systemctl is-active "$unit")" == active ]]
done
for unit in sentinel5.service sentinel7.service orchestrator.service; do
    [[ "$(systemctl is-active "$unit" 2>/dev/null || true)" == inactive ]]
done
printf 'NEXT_ACTION=RUN_REDIS02_TCP_RECHECK_BEFORE_Q132_ACTIVATION_RETRY\n'
