#!/bin/bash
# =============================================================================
# security-password-verify.sh — Multi-Service Credential Verification
# =============================================================================
# Category: security | Bird: falcon | Node-aware: yes
#
# REPORT-ONLY — NO AUTO-HEAL
# DR-043: Old password.sh auto-heal caused credential desync, breaking dashboard.
#         The hourly cron was generating new passwords and overwriting php-fpm env
#         vars without updating db.secret.php, causing ops365 auth failures.
#         This script ONLY reports. Fix with: security-password.sh --send --rotate-db
#
# Cron: 0 */6 * * * (every 6 hours, not hourly — reduces false-positive churn)
# =============================================================================

TOOL_NAME="security-password-verify"
TOOL_VERSION="1.0.0"
TOOL_TIER=0
TOOL_BIRD="falcon"
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}"

# === PATHS ===
CREDENTIAL_REGISTRY="/etc/binary/credential_registry"
DB_SECRET="/opt/binary/web/a.Clean Earth.org/private/db.secret.php"

# =============================================================================
# CREDENTIAL REGISTRY — All managed DB services on this node
# =============================================================================
_init_registry() {
    if [ ! -f "$CREDENTIAL_REGISTRY" ]; then
        mkdir -p "$(dirname "$CREDENTIAL_REGISTRY")" 2>/dev/null
        cat > "$CREDENTIAL_REGISTRY" << 'REGISTRY'
# 365 Credential Registry — Alpha Node
# Format: service|db_user@host|env_or_secret_path|env_var|database
# Created: 2026-05-04 — DR-043 migration from old password.sh
# Updated: 2026-05-04 — Sprint 1 Command Workspace + full service coverage
#
# === PRIMARY (admin dashboard) ===
ops365|ops365@127.0.0.1|/opt/binary/web/a.Clean Earth.org/private/db.secret.php|php_array|s3rv1c3_admin
#
# === ENTERTAINMENT ===
ent_app|ent_app@localhost|/var/www/365entertainment.org/.env|DB_PASSWORD|365_entertainment
admin_entertainment|admin_entertainment@localhost|/var/www/admin.365entertainment.org/.env|DB_PASSWORD|365_entertainment
#
# === BUSINESS ===
biz_portal|biz_portal@localhost|/var/www/365business.org/.env|DB_PASSWORD|365business
#
# === HOSTING ===
hosting_api|365hosting_api@localhost|/var/www/admin.365hosting.org/.env|DB_PASSWORD|365hosting
#
# === PAYMENTS ===
payments_app|payments_app@localhost|/var/www/365payments.org/.env|DB_PASSWORD|payments365
#
# === CLEANLINES ===
cleanlines|cleanlines_user@localhost|/var/www/cleanlines.cc-private/.env|DB_PASS|cleanlines_db
#
# === DNS ===
pdns|pdns@localhost|/etc/pdns/pdns.conf|gmysql-password|pdns
#
# === EMAIL ===
roundcube|roundcube@localhost|/etc/roundcubemail/config.inc.php|db_dsnw|roundcube
#
# === PHOENIX AI ===
admin_phoenix|admin_phoenix@localhost|none|none|db_365phoenix
#
# === DEMO ===
demo2|demo2@localhost|/var/www/demo.365hosting.org/private/db.secret.php|php_array|demo2_db
REGISTRY
        chmod 600 "$CREDENTIAL_REGISTRY"
        echo "  [INIT] Credential registry created: ${CREDENTIAL_REGISTRY}"
    fi
}

_read_registry() {
    grep -v '^#' "$CREDENTIAL_REGISTRY" 2>/dev/null | grep -v '^$'
}

# =============================================================================
# VERIFY — Report-only credential check for all registered services
# =============================================================================
_verify_all() {
    echo "=== Multi-Service Credential Verify: ${NODE_ID} ==="
    echo "  Mode: REPORT-ONLY (no auto-heal — DR-043)"
    echo "  Time: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
    echo ""

    _init_registry

    local ok=0 fail=0 skip=0

    while IFS='|' read -r service db_user env_path env_var database; do
        [ -z "$service" ] && continue

        local user_part="${db_user%%@*}"
        local host_part="${db_user##*@}"

        echo -n "  ${service} (${db_user}): "

        # Skip if no env file configured
        if [ "$env_path" = "none" ]; then
            echo "SKIP (no credential file)"
            skip=$((skip + 1))
            continue
        fi

        if [ ! -f "$env_path" ]; then
            echo "SKIP (file missing: ${env_path})"
            skip=$((skip + 1))
            continue
        fi

        # Extract password based on format
        local current_pw=""
        case "$env_var" in
            php_array)
                # PHP array format: db.secret.php returns ['pass' => '...']
                current_pw=$(php -r "\$c=require '${env_path}'; echo \$c['pass'] ?? '';" 2>/dev/null)
                ;;
            gmysql-password)
                # PowerDNS format: gmysql-password=xxx
                current_pw=$(grep "^${env_var}=" "$env_path" 2>/dev/null | cut -d= -f2-)
                ;;
            db_dsnw)
                # Roundcube DSN: mysql://user:pass@host/db
                current_pw=$(grep 'db_dsnw' "$env_path" 2>/dev/null | sed -n "s|.*://[^:]*:\([^@]*\)@.*|\1|p")
                ;;
            *)
                # Standard .env format: KEY=value
                current_pw=$(grep "^${env_var}=" "$env_path" 2>/dev/null | cut -d= -f2-)
                ;;
        esac

        if [ -z "$current_pw" ]; then
            echo "NO PASSWORD IN ENV"
            fail=$((fail + 1))
            continue
        fi

        # Test DB connectivity (suppress password warning)
        if mysql -u "$user_part" -p"$current_pw" -h "$host_part" -e "SELECT 1" "$database" &>/dev/null; then
            echo "OK"
            ok=$((ok + 1))
        else
            echo "FAILED"
            fail=$((fail + 1))
        fi
    done < <(_read_registry)

    echo ""
    echo "  Verified: ${ok}  Failed: ${fail}  Skipped: ${skip}"

    # Also check primary ops365 via db.secret.php (the dashboard connection)
    if [ -f "$DB_SECRET" ] && command -v php &>/dev/null; then
        local r
        r=$(php -r '
            $c = require "'"$DB_SECRET"'";
            try { new PDO("mysql:host=".$c["host"].";dbname=".$c["name"], $c["user"], $c["pass"]); echo "OK"; }
            catch (Exception $e) { echo "FAIL"; }
        ' 2>/dev/null)
        echo "  Dashboard DB (db.secret.php → PDO): ${r}"
    fi

    echo ""
    tool_audit "verify-all" "ok=${ok} fail=${fail} skip=${skip}"

    [ $fail -gt 0 ] && return 1 || return 0
}

# =============================================================================
# JSON STATUS — For dashboard pill
# =============================================================================
_json_status() {
    _init_registry
    local ok=0 fail=0 skip=0 total=0

    while IFS='|' read -r service db_user env_path env_var database; do
        [ -z "$service" ] && continue
        total=$((total + 1))
        local user_part="${db_user%%@*}"
        local host_part="${db_user##*@}"

        if [ "$env_path" = "none" ] || [ ! -f "$env_path" ]; then
            skip=$((skip + 1))
            continue
        fi

        local current_pw=""
        case "$env_var" in
            php_array) current_pw=$(php -r "\$c=require '${env_path}'; echo \$c['pass'] ?? '';" 2>/dev/null) ;;
            gmysql-password) current_pw=$(grep "^${env_var}=" "$env_path" 2>/dev/null | cut -d= -f2-) ;;
            db_dsnw) current_pw=$(grep 'db_dsnw' "$env_path" 2>/dev/null | sed -n "s|.*://[^:]*:\([^@]*\)@.*|\1|p") ;;
            *) current_pw=$(grep "^${env_var}=" "$env_path" 2>/dev/null | cut -d= -f2-) ;;
        esac

        if [ -z "$current_pw" ]; then fail=$((fail + 1)); continue; fi
        if mysql -u "$user_part" -p"$current_pw" -h "$host_part" -e "SELECT 1" "$database" &>/dev/null; then
            ok=$((ok + 1))
        else
            fail=$((fail + 1))
        fi
    done < <(_read_registry)

    local status="healthy"
    [ $fail -gt 0 ] && status="degraded"
    [ $fail -gt 3 ] && status="critical"

    cat <<EOF
{"tool":"${TOOL_NAME}","node":"${NODE_ID}","status":"${status}","services_ok":${ok},"services_fail":${fail},"services_skip":${skip},"services_total":${total},"checked_at":"$(date -u +%Y-%m-%dT%H:%M:%SZ)"}
EOF
}

# =============================================================================
# STANDARD TOOL INTERFACE
# =============================================================================
_do_send_impl()   { _verify_all; }
_do_status_impl() { _json_status; }
_do_digest_impl() { _verify_all; }
_do_flush_impl()  { echo "Nothing to flush."; }

tool_help() {
    echo "${TOOL_NAME} v${TOOL_VERSION} — Multi-Service Credential Verifier"
    echo ""
    echo "REPORT-ONLY — No auto-heal (DR-043)"
    echo ""
    echo "Actions:"
    echo "  --send       Verify all registered service credentials"
    echo "  --status     JSON pill for dashboard"
    echo "  --digest     Same as --send"
    echo ""
    echo "Registry: ${CREDENTIAL_REGISTRY}"
    echo "Fix failed: security-password.sh --send --rotate-db"
}

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 "$@" ;;
    --help) tool_help ;; *) handle_standard_command "$@" ;;
esac
