#!/bin/bash
# =============================================================================
# WOOO AIOps - Offsite backup / credential escrow evidence report
# 2026-05-06 ogt + Codex: 產出可交接、可告警研判的紅acted 證據摘要。
#
# 預設只讀，不觸發 rclone remote status、不上傳、不寫 success marker。
# 如需確認 Google Drive/rclone remote 可列出，明確加 --include-remote-status。
# =============================================================================

set -euo pipefail

BACKUP_BASE="${BACKUP_BASE:-/backup}"
SCRIPTS_DIR="${BACKUP_SCRIPTS_DIR:-${BACKUP_BASE}/scripts}"
OFFSITE_DIR="${BACKUP_OFFSITE_STATUS_DIR:-${BACKUP_BASE}/offsite}"
ESCROW_DIR="${BACKUP_ESCROW_EVIDENCE_DIR:-${BACKUP_BASE}/escrow-evidence}"
TEXTFILE_PROM="${BACKUP_HEALTH_PROM:-/home/wooo/node_exporter_textfiles/backup_health.prom}"
INCLUDE_REMOTE_STATUS=0
NO_COLOR=0

CONFIG_B2_SCRIPT="${SCRIPTS_DIR}/configure-offsite-b2.sh"
CONFIG_RCLONE_SCRIPT="${SCRIPTS_DIR}/configure-offsite-rclone.sh"
READINESS_SCRIPT="${SCRIPTS_DIR}/backup-offsite-readiness-gate.sh"
SYNC_SCRIPT="${SCRIPTS_DIR}/sync-offsite-backups.sh"
ESCROW_SCRIPT="${SCRIPTS_DIR}/mark-credential-escrow-verified.sh"

usage() {
    cat <<'USAGE'
Usage:
  offsite-escrow-evidence-report.sh [--no-color]
  offsite-escrow-evidence-report.sh --include-remote-status [--no-color]

Rules:
  - Default mode is read-only and does not query remote provider.
  - --include-remote-status runs sync-offsite-backups.sh --mode status only.
  - This report must never print credential values.
  - Use it after reboot, after Google Drive/rclone config, after small sync, and before full sync review.
USAGE
}

while [ "$#" -gt 0 ]; do
    case "$1" in
        --include-remote-status)
            INCLUDE_REMOTE_STATUS=1
            shift
            ;;
        --no-color)
            NO_COLOR=1
            shift
            ;;
        -h|--help)
            usage
            exit 0
            ;;
        *)
            echo "Unknown argument: $1" >&2
            usage >&2
            exit 2
            ;;
    esac
done

if [ "${NO_COLOR}" = "1" ]; then
    green=""
    yellow=""
    red=""
    reset=""
else
    green="$(printf '\033[32m')"
    yellow="$(printf '\033[33m')"
    red="$(printf '\033[31m')"
    reset="$(printf '\033[0m')"
fi

redact_output() {
    sed -E \
        -e '/CONFIGURED=/! s/^([[:space:]]*(export[[:space:]]+)?[A-Za-z_][A-Za-z0-9_]*(KEY|TOKEN|PASSWORD|SECRET)[A-Za-z0-9_]*=).*/\1<redacted>/I' \
        -e '/CONFIGURED=/! s/^([[:space:]]*B2_APPLICATION_KEY=).*/\1<redacted>/'
}

section() {
    echo
    echo "== $* =="
}

tool_status() {
    local title="$1"
    shift
    local rc=0
    local output=""
    section "${title}"
    if output="$("$@" 2>&1)"; then
        printf "%sOK%s rc=0 command=%s\n" "${green}" "${reset}" "$*"
    else
        rc=$?
        printf "%sWARN%s rc=%s command=%s\n" "${yellow}" "${reset}" "${rc}" "$*"
    fi
    printf "%s\n" "${output}" | redact_output
    return "${rc}"
}

marker_timestamp() {
    local path="$1"
    [ -f "${path}" ] || {
        echo 0
        return
    }
    awk -F= '/^timestamp=/ {print int($2); found=1; exit} END {if (!found) print 0}' "${path}" 2>/dev/null || echo 0
}

marker_state() {
    local label="$1"
    local path="$2"
    local ts
    ts="$(marker_timestamp "${path}")"
    if [ "${ts}" -gt 0 ]; then
        printf "%sOK%s %s present timestamp=%s path=%s\n" "${green}" "${reset}" "${label}" "${ts}" "${path}"
        return 0
    fi
    printf "%sWARN%s %s missing path=%s\n" "${yellow}" "${reset}" "${label}" "${path}"
    return 1
}

script_state() {
    local path="$1"
    if [ -x "${path}" ]; then
        printf "%sOK%s script executable: %s\n" "${green}" "${reset}" "${path}"
        return 0
    fi
    printf "%sBLOCKED%s script missing or not executable: %s\n" "${red}" "${reset}" "${path}"
    return 1
}

AWOOOI_OFFSITE_ESCROW_REPORT_VERSION="2026-05-19.v2"
echo "AWOOOI offsite / credential escrow evidence report"
date
echo "REPORT_VERSION=${AWOOOI_OFFSITE_ESCROW_REPORT_VERSION}"
echo "BACKUP_BASE=${BACKUP_BASE}"
echo "SCRIPTS_DIR=${SCRIPTS_DIR}"
echo "INCLUDE_REMOTE_STATUS=${INCLUDE_REMOTE_STATUS}"

section "script presence"
missing_scripts=0
for path in "${CONFIG_RCLONE_SCRIPT}" "${READINESS_SCRIPT}" "${SYNC_SCRIPT}" "${ESCROW_SCRIPT}"; do
    script_state "${path}" || missing_scripts=$((missing_scripts + 1))
done
[ -x "${CONFIG_B2_SCRIPT}" ] && script_state "${CONFIG_B2_SCRIPT}" || true

config_rc=99
readiness_rc=99
remote_rc=0
escrow_rc=99
rclone_ready=0
b2_ready=0
offsite_ready=0
readiness_blocked=0
escrow_missing=0

if [ -x "${CONFIG_RCLONE_SCRIPT}" ]; then
    config_output="$("${CONFIG_RCLONE_SCRIPT}" --status 2>&1)" || config_rc=$?
    [ "${config_rc}" = "99" ] && config_rc=0
    section "rclone local config status"
    printf "RC=%s command=%s --status\n" "${config_rc}" "${CONFIG_RCLONE_SCRIPT}"
    printf "%s\n" "${config_output}" | redact_output
    if grep -q "RCLONE_REMOTE_CONFIGURED=1" <<<"${config_output}"; then
        rclone_ready=1
    fi
fi

if [ -x "${CONFIG_B2_SCRIPT}" ]; then
    b2_output="$("${CONFIG_B2_SCRIPT}" --status 2>&1)" || true
    section "legacy b2 local config status"
    printf "RC=0 command=%s --status\n" "${CONFIG_B2_SCRIPT}"
    printf "%s\n" "${b2_output}" | redact_output
    if grep -q "B2_ACCOUNT_ID_CONFIGURED=1" <<<"${b2_output}" \
        && grep -q "B2_APPLICATION_KEY_CONFIGURED=1" <<<"${b2_output}" \
        && grep -q "B2_BUCKET_CONFIGURED=1" <<<"${b2_output}"; then
        b2_ready=1
    fi
fi
if [ "${rclone_ready}" -eq 1 ] || [ "${b2_ready}" -eq 1 ]; then
    offsite_ready=1
fi

if [ -x "${READINESS_SCRIPT}" ]; then
    tool_status "offsite readiness status" "${READINESS_SCRIPT}" --status --no-color || readiness_rc=$?
    [ "${readiness_rc}" = "99" ] && readiness_rc=0
    if "${READINESS_SCRIPT}" --status --require-configured --no-color >/tmp/awoooi-offsite-evidence-readiness-require.log 2>&1; then
        readiness_blocked=0
    else
        readiness_blocked=1
    fi
fi

if [ "${INCLUDE_REMOTE_STATUS}" = "1" ] && [ -x "${SYNC_SCRIPT}" ]; then
    tool_status "offsite remote status" "${SYNC_SCRIPT}" --mode status || remote_rc=$?
fi

if [ -x "${ESCROW_SCRIPT}" ]; then
    escrow_output="$("${ESCROW_SCRIPT}" --status 2>&1)" || escrow_rc=$?
    [ "${escrow_rc}" = "99" ] && escrow_rc=0
    section "credential escrow status"
    printf "RC=%s command=%s --status\n" "${escrow_rc}" "${ESCROW_SCRIPT}"
    printf "%s\n" "${escrow_output}" | redact_output
    escrow_missing="$(grep -c " missing" <<<"${escrow_output}" || true)"
    if [ "${escrow_missing}" -gt 0 ]; then
        section "credential escrow missing command template"
        echo "以下命令只接受非 secret evidence-id；請把 EVIDENCE_ID_FOR_* 換成密碼管理器項目 ID、工單 ID、sealed envelope ID 或 recovery checklist ID。"
        echo "直接執行 placeholder 會被拒絕；可先加 --dry-run 驗證 evidence-id，不會寫 marker。"
        BACKUP_COMMON_QUIET=1 "${ESCROW_SCRIPT}" --missing-commands | redact_output
    fi
fi

section "offsite markers"
partial_marker=0
full_marker=0
marker_state "partial offsite marker" "${OFFSITE_DIR}/b2-partial-last-success" && partial_marker=1 || true
marker_state "full offsite marker" "${OFFSITE_DIR}/b2-last-success" && full_marker=1 || true
marker_state "partial offsite marker (rclone)" "${OFFSITE_DIR}/rclone-partial-last-success" && partial_marker=1 || true
marker_state "full offsite marker (rclone)" "${OFFSITE_DIR}/rclone-last-success" && full_marker=1 || true

section "prometheus textfile evidence"
if [ -r "${TEXTFILE_PROM}" ]; then
    grep -E 'awoooi_backup_offsite_|awoooi_backup_credential_escrow_' "${TEXTFILE_PROM}" | redact_output || true
else
    printf "%sWARN%s backup health textfile missing or unreadable: %s\n" "${yellow}" "${reset}" "${TEXTFILE_PROM}"
fi

section "next step"
if [ "${missing_scripts}" -gt 0 ]; then
    echo "NEXT_STEP=deploy_backup_jobs_with_ansible"
    echo "DETAIL=先套用 110-devops.yml --tags backup_jobs，補齊 /backup/scripts。"
elif [ "${offsite_ready}" -ne 1 ]; then
    echo "NEXT_STEP=configure_google_drive_rclone_on_110_tty"
    echo "DETAIL=在 110 本機執行 configure-offsite-rclone.sh --interactive；完成 Google Drive OAuth 後，只把非 secret remote 設定寫入 offsite.env。"
elif [ "${readiness_blocked}" -ne 0 ]; then
    echo "NEXT_STEP=fix_offsite_readiness_blockers"
    echo "DETAIL=先看 backup-offsite-readiness-gate.sh --status --require-configured --no-color 的 BLOCKED 項目。"
elif [ "${partial_marker}" -ne 1 ]; then
    echo "NEXT_STEP=run_small_dry_run_then_partial_sync"
    echo "DETAIL=先跑 backup-offsite-readiness-gate.sh --dry-run-small，再只同步 ai-artifacts public-routes。"
elif [ "${escrow_missing}" -gt 0 ]; then
    echo "NEXT_STEP=complete_credential_escrow_review"
    echo "DETAIL=人工確認金庫可用後，用 mark-credential-escrow-verified.sh 寫非 secret evidence-id marker。"
elif [ "${full_marker}" -ne 1 ]; then
    echo "NEXT_STEP=pre_full_sync_review"
    echo "DETAIL=低峰窗口前跑 backup-offsite-readiness-gate.sh --pre-full-sync --require-configured --require-escrow --no-color。"
else
    echo "NEXT_STEP=offsite_and_escrow_ready"
    echo "DETAIL=維持每日 status、每週 integrity check、每月 restore drill 與 escrow review。"
fi

section "summary"
echo "SCRIPT_MISSING_COUNT=${missing_scripts}"
echo "OFFSITE_CONFIGURED=${offsite_ready}"
echo "RCLONE_CONFIGURED=${rclone_ready}"
echo "B2_CONFIGURED=${b2_ready}"
echo "READINESS_REQUIRE_CONFIGURED_BLOCKED=${readiness_blocked}"
echo "REMOTE_STATUS_INCLUDED=${INCLUDE_REMOTE_STATUS}"
echo "REMOTE_STATUS_RC=${remote_rc}"
echo "ESCROW_MISSING_COUNT=${escrow_missing}"
echo "PARTIAL_MARKER_PRESENT=${partial_marker}"
echo "FULL_MARKER_PRESENT=${full_marker}"
