#!/usr/bin/env bash
#
# homelab-infrastructure-review.sh
# Triggers a full, intelligent, context-aware reconciliation audit.
#

set -euo pipefail

# ── Configuration & Logging ──────────────────────────────────────────────────
AUDIT_CONFIG_FILE="/srv/configs/ai/skills/homelab-infrastructure-review/scripts/audit_config.yaml"
INFRA_FILE="/srv/docs/public/projects/homelab/homelab_Infra.md"
LOCK_FILE="/srv/configs/ai/.audit.lock"
log_info() { echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') $*"; }
log_error() { echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') $*" >&2; }

# ── Pre-flight & Lock ────────────────────────────────────────────────────────
acquire_lock() {
    if [ -f "$LOCK_FILE" ]; then
        local pid; pid=$(cat "$LOCK_FILE" 2>/dev/null)
        if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
            log_error "Audit already running (PID $pid). Aborting."; exit 1
        fi
        log_info "Stale lock file found. Cleaning up."; rm -f "$LOCK_FILE"
    fi
    echo $$ > "$LOCK_FILE"; trap 'rm -f "$LOCK_FILE"' EXIT
}
preflight_checks() {
    if [ ! -f "$AUDIT_CONFIG_FILE" ]; then log_error "audit_config.yaml not found. Aborting."; exit 1; fi
    log_info "All pre-flight checks passed."
}

# ── Data Sources ─────────────────────────────────────────────────────────────
get_infra_docs() {
    local in_services_section=false
    while IFS= read -r line || [ -n "$line" ]; do
        if [[ "$line" =~ ^##[[:space:]]+(Docker|Truenas)[[:space:]]+services ]]; then
            in_services_section=true
        elif [[ "$line" =~ ^##[[:space:]] && ! "$line" =~ ^##[[:space:]]+(Docker|Truenas)[[:space:]]+services ]]; then
            in_services_section=false
        fi
        if $in_services_section && [[ "$line" =~ ^\|[[:space:]]*\*\*([a-zA-Z0-9_-]+)\*\* ]]; then
            IFS='|' read -r _ name _ <<< "$line"; printf '%s\n' "$(echo "$name" | tr -d '*' | xargs)"
        fi
    done < "$INFRA_FILE"
}
get_live_docker_containers() {
    while IFS= read -r line; do
        local name; name=$(echo "$line" | jq -r '.Names')
        local health; health=$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}no_health_check{{end}}' "$name" 2>/dev/null || echo "error")
        local status;
        case "$health" in
            healthy) status="healthy";;
            unhealthy) status="UNHEALTHY";;
            *) status="no_health_check";;
        esac
        printf '%s|%s\n' "$name" "$status"
    done <<< "$(docker ps --format '{{json .}}')"
}
get_mcp_nodes() {
    local service_key=""; if [ -f "/srv/configs/docker_compose/homelabel/.env" ]; then service_key=$(grep -E "^MCP_SERVICE_KEY=" "/srv/configs/docker_compose/homelabel/.env" | cut -d'=' -f2-); fi
    curl -s -H "X-MCP-Service-Key: $service_key" "http://localhost:9445/api/v1/nodes" | jq -r '.[]? | .label // .name // "unknown"'
}

# ── Reconciliation Engine ────────────────────────────────────────────────────
if [ -f "$AUDIT_CONFIG_FILE" ]; then
    source <(python3 /srv/configs/ai/skills/homelab-infrastructure-review/scripts/load_config.py "$AUDIT_CONFIG_FILE")
fi

reconcile() {
    local doc_services=(); while IFS= read -r name; do doc_services+=("$(echo "$name"|tr '[:upper:]' '[:lower:]')"); done < <(get_infra_docs)
    local live_services=(); local untracked_report=""; local unhealthy_report=""
    
    while IFS='|' read -r name status; do
        local lower_name; lower_name=$(echo "$name" | tr '[:upper:]' '[:lower:]')
        live_services+=("$lower_name")
        if [[ " ${IGNORE_CONTAINERS} " == *" ${lower_name} "* ]]; then continue; fi
        
        local found=false; for doc in "${doc_services[@]}"; do [ "$lower_name" = "$doc" ] && found=true && break; done
        local alias_var="SERVICE_ALIAS_${lower_name//-/_}"
        if ! $found && [[ -v $alias_var ]]; then
            local target="${!alias_var}"; for doc in "${doc_services[@]}"; do [ "$target" = "$doc" ] && found=true && break; done
        fi
        
        if ! $found; then untracked_report+="  ⚠ **$name** is running but not documented.\n"; fi
        if [[ "$status" == "UNHEALTHY" ]]; then unhealthy_report+="  ✗ **$name** is **UNHEALTHY**.\n"; fi
    done < <(get_live_docker_containers)
    
    local missing_report=""
    for doc in "${doc_services[@]}"; do
        if [ "$doc" = "dev" ] || [ "$doc" = "calibre" ]; then continue; fi # Exceptions
        local found=false; for live in "${live_services[@]}"; do [ "$doc" = "$live" ] && found=true && break; done
        if ! $found; then missing_report+="  ✗ **$doc** is documented but not running.\n"; fi
    done
    
    local mcp_nodes=(); while IFS= read -r label; do mcp_nodes+=("$(echo "$label"|tr '[:upper:]' '[:lower:]'|tr ' _-' '    ')"); done < <(get_mcp_nodes)
    local canvas_report=""
    for name in "${live_services[@]}"; do
        if [[ " ${IGNORE_CONTAINERS} " == *" ${name} "* ]]; then continue; fi
        local found=false; for node in "${mcp_nodes[@]}"; do [[ "$node" == *"$name"* || "$name" == *"$node"* ]] && found=true && break; done
        local alias_var="CANVAS_ALIAS_${name//-/_}"
        if ! $found && [[ -v $alias_var ]]; then
            local target="${!alias_var}"; for node in "${mcp_nodes[@]}"; do [ "$target" = "$node" ] && found=true && break; done
        fi
        if ! $found; then canvas_report+="  ⚠ **$name** is running but not on the canvas.\n"; fi
    done
    
    printf "## Homelab Audit Report\nGenerated: $(date)\n\n"
    printf "### Docker vs. Documentation\n"
    if [ -z "$untracked_report$missing_report$unhealthy_report" ]; then
        printf "  ✅ All services are aligned and healthy.\n"
    else
        printf "%s%s%s" "$untracked_report" "$missing_report" "$unhealthy_report"
    fi
    printf "\n### Docker vs. Canvas\n"
    if [ -z "$canvas_report" ]; then printf "  ✅ All services are mapped.\n"; else printf "%s" "$canvas_report"; fi
}

# ── Main Execution ───────────────────────────────────────────────────────────
main() {
    log_info "Starting Homelab Infrastructure Audit"
    acquire_lock
    preflight_checks
    log_info "Running reconciliation..."
    reconcile
}

main "$@"
