#!/usr/bin/env bash

set -Eeuo pipefail
export LANG=C

EXPECTED_HOSTNAME="sqjcapp01"
EXPECTED_IPV4="10.2.203.104"
EXPECTED_TAR_SHA256="d087c3b0fd1816a740da9d79682d4a5a2c3b6a5c55abd1776854d4e44dc6c5cb"
EXPECTED_SOURCE_COMMIT="fb48b4d4"
FRAMEWORK_TAR="/root/sanquan-app-q050-role-framework-fb48b4d4.tar.gz"
BUNDLE_ROOT="/opt/zhct-deploy"
BACKUP_ROOT="/var/backups/zhct-q050"

die() {
  printf 'ERROR: %s\n' "$*" >&2
  exit 1
}

[[ "${EUID}" -eq 0 ]] || die "must run as root"
[[ $# -eq 1 ]] || die "usage: $0 <q050-baseline-run-id>"
RUN_ID="$1"
[[ "${RUN_ID}" =~ ^[0-9]{8}T[0-9]{6}[+-][0-9]{4}$ ]] || die "invalid run id"
EVIDENCE_DIR="${BACKUP_ROOT}/${RUN_ID}"
BACKUP_DIR="${EVIDENCE_DIR}/app-role-framework-before-fb48b4d4"

[[ "$(hostname -s)" == "${EXPECTED_HOSTNAME}" ]] || die "hostname mismatch"
ip -o -4 addr show scope global | awk '{print $4}' | cut -d/ -f1 | \
  grep -Fxq "${EXPECTED_IPV4}" || die "expected IPv4 is not configured"
[[ -d "${EVIDENCE_DIR}/baseline" ]] || die "Q-050 baseline evidence is missing"
[[ -f "${EVIDENCE_DIR}/result.env" ]] || die "Q-050 baseline result is missing"
grep -Fxq 'target_listener_check=PASS' "${EVIDENCE_DIR}/result.env" || \
  die "Q-050 baseline target listener gate is not PASS"
[[ "$(sha256sum "${FRAMEWORK_TAR}" | awk '{print $1}')" == "${EXPECTED_TAR_SHA256}" ]] || \
  die "framework tar SHA256 mismatch"
[[ ! -e "${BACKUP_DIR}" ]] || die "framework backup directory already exists"

umask 077
STAGING_ROOT=$(mktemp -d /opt/q050-app-framework.XXXXXX)
cleanup() {
  [[ ! -d "${STAGING_ROOT}" ]] || rm -rf -- "${STAGING_ROOT}"
}
trap cleanup EXIT

tar -xzf "${FRAMEWORK_TAR}" -C "${STAGING_ROOT}"
for path in common roles/app README.md bundle-sha256.sh; do
  [[ -e "${STAGING_ROOT}/${path}" ]] || die "framework member is missing: ${path}"
done

metadata_artifact=$(find "${STAGING_ROOT}" -type f \
  \( -name '._*' -o -name '.DS_Store' \) -print -quit)
[[ -z "${metadata_artifact}" ]] || die "framework contains metadata artifact: ${metadata_artifact}"
while IFS= read -r -d '' script; do
  bash -n "${script}"
done < <(find "${STAGING_ROOT}/common" "${STAGING_ROOT}/roles/app" \
  -type f -name '*.sh' -print0 | sort -z)

install -d -m 0700 "${BACKUP_DIR}" "${BACKUP_DIR}/roles"
if [[ -d "${BUNDLE_ROOT}/common" ]]; then
  mv "${BUNDLE_ROOT}/common" "${BACKUP_DIR}/common"
fi
if [[ -d "${BUNDLE_ROOT}/roles/app" ]]; then
  mv "${BUNDLE_ROOT}/roles/app" "${BACKUP_DIR}/roles/app"
fi
for file in README.md bundle-sha256.sh .source-commit .framework-bundle-sha256; do
  [[ -f "${BUNDLE_ROOT}/${file}" ]] && cp -p "${BUNDLE_ROOT}/${file}" "${BACKUP_DIR}/${file}"
done

install -d -m 0750 "${BUNDLE_ROOT}" "${BUNDLE_ROOT}/roles" "${BUNDLE_ROOT}/packages"
mv "${STAGING_ROOT}/common" "${BUNDLE_ROOT}/common"
mv "${STAGING_ROOT}/roles/app" "${BUNDLE_ROOT}/roles/app"
install -m 0640 "${STAGING_ROOT}/README.md" "${BUNDLE_ROOT}/README.md"
install -m 0750 "${STAGING_ROOT}/bundle-sha256.sh" "${BUNDLE_ROOT}/bundle-sha256.sh"
printf '%s\n' "${EXPECTED_SOURCE_COMMIT}" >"${BUNDLE_ROOT}/.source-commit"
printf '%s\n' "${EXPECTED_TAR_SHA256}" >"${BUNDLE_ROOT}/.framework-bundle-sha256"
chown -R root:root "${BUNDLE_ROOT}/common" "${BUNDLE_ROOT}/roles/app"
chmod -R go-w "${BUNDLE_ROOT}/common" "${BUNDLE_ROOT}/roles/app"

{
  printf 'captured_at=%s\n' "$(date --iso-8601=seconds)"
  printf 'source_commit=%s\n' "${EXPECTED_SOURCE_COMMIT}"
  printf 'framework_bundle_sha256=%s\n' "${EXPECTED_TAR_SHA256}"
  printf 'metadata_artifact_count=0\n'
  printf 'shell_syntax_check=PASS\n'
  printf 'install_execution=NOT_PERFORMED\n'
  printf 'service_start=NOT_PERFORMED\n'
  printf 'application_release=NOT_PERFORMED\n'
} >"${EVIDENCE_DIR}/framework-fb48b4d4-refresh-result.env"

find "${BUNDLE_ROOT}/common" "${BUNDLE_ROOT}/roles/app" \
  -xdev -type f -print0 | sort -z | xargs -0 sha256sum \
  >"${EVIDENCE_DIR}/framework-fb48b4d4-files.sha256"
chmod -R go-rwx "${BACKUP_DIR}"
chmod 0600 "${EVIDENCE_DIR}"/framework-fb48b4d4-*

printf 'Q050_APP_FRAMEWORK_REFRESH_OK\n'
cat "${EVIDENCE_DIR}/framework-fb48b4d4-refresh-result.env"
