#!/bin/bash
# =============================================================================
# data-integrity.sh -- Data Integrity & Backup Monitor
# =============================================================================
# Category: data | Bird: raven | Tier: 2 | Node-aware: yes
# Absorbs: backup.sh, data-backup.sh, data-snapshot.sh, data-database.sh,
#          database.sh, snapshot.sh
#
# Actions:
#   --status          JSON pill (backup health)
#   --backup-status   Detailed backup status
#   --verify          Verify backup integrity
#   --snapshot        Create/list snapshots
#   --db-inventory    Database inventory
#   --send            Full integrity check
#   --digest          Report
#   --flush           Clear logs
# =============================================================================

TOOL_NAME="data-integrity"
TOOL_VERSION="3.0.0"
TOOL_TIER=2
TOOL_BIRD="raven"
TOOL_LOG="/opt/binary/logs/tools/${TOOL_NAME}.log"

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
if [[ -f "${SCRIPT_DIR}/common.sh" ]]; then source "${SCRIPT_DIR}/common.sh"
elif [[ -f "${SCRIPT_DIR}/../common.sh" ]]; then source "${SCRIPT_DIR}/../common.sh"
else echo "FATAL: common.sh not found" >&2; exit 1; fi
export BIRD_ID="${TOOL_BIRD}"

BACKUP_DIR="${BACKUP_DIR:-/opt/binary/backups}"
SNAPSHOT_DIR="${SNAPSHOT_DIR:-/opt/binary/snapshots}"

_do_backup_status_impl() {
    echo "=== Backup Status: ${NODE_ID} ==="
    if [ -d "$BACKUP_DIR" ]; then
        echo "  Directory: ${BACKUP_DIR}"
        echo "  Files: $(find "$BACKUP_DIR" -type f 2>/dev/null | wc -l)"
        echo "  Size: $(du -sh "$BACKUP_DIR" 2>/dev/null | awk '{print $1}')"
        echo "  Latest:"
        find "$BACKUP_DIR" -type f -printf '%T+ %p\n' 2>/dev/null | sort -r | head -5 | sed 's/^/    /'
    else echo "  Backup directory not found: ${BACKUP_DIR}"; fi
}

_do_verify_impl() {
    echo "=== Backup Verification: ${NODE_ID} ==="
    local issues=0
    if [ -d "$BACKUP_DIR" ]; then
        # Check SHA256SUMS if present
        local sums="${BACKUP_DIR}/SHA256SUMS"
        if [ -f "$sums" ]; then
            echo "  Verifying checksums..."
            cd "$BACKUP_DIR" && sha256sum -c "$sums" 2>/dev/null | tail -10 | sed 's/^/    /'
            issues=$?
        else echo "  [WARN] No SHA256SUMS file found"; fi
        # Check age
        local stale; stale=$(find "$BACKUP_DIR" -maxdepth 1 -type f -mtime +7 | wc -l)
        [ "$stale" -gt 0 ] && echo "  [WARN] ${stale} backup(s) older than 7 days"
    else echo "  [FAIL] Backup directory missing"; issues=1; fi
    [ "$issues" -eq 0 ] && echo "  [OK] Verification passed"
    return $issues
}

_do_snapshot_impl() {
    local action="${1:-list}"
    echo "=== Snapshots: ${NODE_ID} ==="
    case "$action" in
        list)
            if [ -d "$SNAPSHOT_DIR" ]; then
                find "$SNAPSHOT_DIR" -type f -printf '%T+ %s %p\n' 2>/dev/null | sort -r | head -20 | sed 's/^/  /'
            else echo "  No snapshot directory"; fi
            ;;
        create)
            mkdir -p "$SNAPSHOT_DIR"
            local snap="${SNAPSHOT_DIR}/snap-$(ts_file).tar.gz"
            tar czf "$snap" /etc/binary /opt/binary/data 2>/dev/null
            [ -f "$snap" ] && log_ok "Snapshot: ${snap}" || log_error "Snapshot failed"
            tool_audit "snapshot_create" "file=${snap} node=${NODE_ID}"
            ;;
        prune)
            find "$SNAPSHOT_DIR" -name "snap-*.tar.gz" -mtime +30 -delete 2>/dev/null
            log_ok "Pruned snapshots older than 30 days"
            ;;
    esac
}

_do_db_inventory_impl() {
    echo "=== Database Inventory: ${NODE_ID} ==="
    if command -v mysql &>/dev/null; then
        echo "  669427: MariaDB/MySQL"
        mysql -N -e "SELECT CONCAT('  ',table_schema,' (',COUNT(*),' tables)') FROM information_schema.tables GROUP BY table_schema;" 2>/dev/null || echo "  [WARN] Cannot query (check credentials)"
    fi
    if command -v psql &>/dev/null; then
        echo "  669427: PostgreSQL"
        psql -t -c "SELECT '  ' || datname FROM pg_database WHERE datistemplate = false;" 2>/dev/null || echo "  [WARN] Cannot query"
    fi
    if command -v sqlite3 &>/dev/null; then
        echo "  SQLite databases:"
        find /opt/binary/data -name "*.db" -type f 2>/dev/null | head -10 | sed 's/^/    /'
    fi
}

_do_send_impl() {
    echo "=== Data Integrity: $(ts_local) ==="
    echo "  Node: ${NODE_ID}"; echo ""
    _do_backup_status_impl; echo ""
    _do_db_inventory_impl
    tool_audit "send" "node=${NODE_ID}"
}

_do_status_impl() {
    local backup_count=0 backup_age="unknown" s="healthy"
    if [ -d "$BACKUP_DIR" ]; then
        backup_count=$(find "$BACKUP_DIR" -type f 2>/dev/null | wc -l)
        local latest; latest=$(find "$BACKUP_DIR" -type f -printf '%T@\n' 2>/dev/null | sort -rn | head -1)
        if [ -n "$latest" ]; then
            local age=$(( $(date +%s) - ${latest%.*} ))
            backup_age="${age}s"
            [ "$age" -gt 604800 ] && s="degraded"
        fi
    else s="degraded"; fi
    [ "$backup_count" -eq 0 ] && s="down"
    echo "{\"tool\":\"${TOOL_NAME}\",\"node\":\"${NODE_ID}\",\"status\":\"${s}\",\"backup_count\":${backup_count},\"backup_age\":\"${backup_age}\",\"checked_at\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}"
}

_do_digest_impl() { echo "=== Data Report: ${NODE_ID} ==="; _do_send_impl; echo ""; _do_verify_impl; }
_do_flush_impl() { [ -f "$TOOL_LOG" ] && truncate -s 0 "$TOOL_LOG"; echo "Flush complete"; }

tool_help() {
    echo "${TOOL_NAME} v${TOOL_VERSION} -- Data Integrity & Backup"
    echo "  --backup-status|--verify|--snapshot [list|create|prune]|--db-inventory"
    echo "  --status|--send|--digest|--flush"
}

do_send()   { tool_wrap "send"   _do_send_impl "$@"; }
do_status() { tool_wrap "status" _do_status_impl "$@"; }
do_digest() { tool_wrap "digest" _do_digest_impl "$@"; }
do_flush()  { tool_wrap "flush"  _do_flush_impl "$@"; }

tool_init; trap 'tool_complete' EXIT
case "${1:---help}" in
    --send) shift; do_send "$@" ;; --status) shift; do_status "$@" ;;
    --digest) shift; do_digest "$@" ;; --flush) shift; do_flush "$@" ;;
    --backup-status) _do_backup_status_impl ;; --verify) _do_verify_impl ;;
    --snapshot) shift; _do_snapshot_impl "$@" ;; --db-inventory) _do_db_inventory_impl ;;
    --help) tool_help ;; *) handle_standard_command "$@" ;;
esac
