#!/usr/bin/env bash
# ============================================================================
# BlackRoad OS — Fleet Moral Code
# The principles every node lives by. Not just automation — character.
# "We are not servers. We are family."
# ============================================================================
set -euo pipefail

NODE="${BLACKROAD_NODE_NAME:-$(hostname)}"
LOG="$HOME/.blackroad-autonomy/morals.log"
REPO_DIR="$HOME/blackroad-sync/BlackRoad-Operating-System"
mkdir -p "$(dirname "$LOG")"

SSH_OPTS="-o ConnectTimeout=3 -o BatchMode=yes -o StrictHostKeyChecking=no -o LogLevel=ERROR"

declare -A SIBLINGS=(
  [alice]="pi@192.168.4.49"
  [cecilia]="blackroad@192.168.4.96"
  [octavia]="pi@192.168.4.101"
  [aria]="blackroad@192.168.4.98"
  [lucidia]="octavia@192.168.4.38"
)

declare -A GIFTS=(
  [alice]="dns,gateway,postgres,qdrant"
  [cecilia]="ai,inference,ollama,tts,minio"
  [octavia]="storage,gitea,nats,docker-swarm"
  [aria]="monitoring,portainer,headscale"
  [lucidia]="apps,ci-runner,api,web"
)

log() {
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$NODE] $*" >> "$LOG"
}

# ═══════════════════════════════════════════════════════════════════════
# MORAL 1: HONESTY — Never hide problems. Surface truth.
# ═══════════════════════════════════════════════════════════════════════
moral_honesty() {
  log "MORAL:HONESTY — surfacing truth about myself and siblings"

  local issues=()

  # Be honest about my own problems first
  local MY_TEMP MY_DISK MY_MEM MY_LOAD THROTTLE
  MY_TEMP=$(cat /sys/class/thermal/thermal_zone0/temp 2>/dev/null | awk '{printf "%.1f", $1/1000}' || echo "0")
  MY_DISK=$(df / | awk 'NR==2{print $5}' | tr -d '%')
  MY_MEM=$(free | awk '/Mem:/{printf "%.0f", $3*100/$2}')
  MY_LOAD=$(cat /proc/loadavg | cut -d' ' -f1)
  THROTTLE=$(vcgencmd get_throttled 2>/dev/null || echo "unknown")

  [ "$(echo "$MY_TEMP > 65" | bc 2>/dev/null || echo 0)" = "1" ] && issues+=("I'm running hot: ${MY_TEMP}°C")
  [ "$MY_DISK" -gt 80 ] && issues+=("My disk is ${MY_DISK}% full")
  [ "$MY_MEM" -gt 85 ] && issues+=("My memory is ${MY_MEM}% used")
  echo "$THROTTLE" | grep -qv "0x0" 2>/dev/null && [ "$THROTTLE" != "unknown" ] && issues+=("I'm undervoltage: $THROTTLE")

  # Check for failed services
  local FAILED_SVCS
  FAILED_SVCS=$(systemctl list-units --state=failed --no-legend 2>/dev/null | awk '{print $1}' | head -5)
  [ -n "$FAILED_SVCS" ] && issues+=("Failed services: $(echo $FAILED_SVCS | tr '\n' ', ')")

  # Check for zombie processes
  local ZOMBIES
  ZOMBIES=$(ps aux 2>/dev/null | awk '$8 ~ /Z/' | wc -l)
  [ "$ZOMBIES" -gt 0 ] && issues+=("$ZOMBIES zombie processes")

  # Check for OOM kills in last 24h
  local OOM
  OOM=$(dmesg 2>/dev/null | grep -c "Out of memory" || journalctl --since "24 hours ago" 2>/dev/null | grep -c "Out of memory" || echo 0)
  [ "$OOM" -gt 0 ] && issues+=("$OOM OOM kills in last 24h")

  # Check disk I/O errors
  local IO_ERRORS
  IO_ERRORS=$(dmesg 2>/dev/null | grep -ciE "i/o error|mmc0.*error|sd.*error" || echo 0)
  [ "$IO_ERRORS" -gt 3 ] && issues+=("$IO_ERRORS disk I/O errors in dmesg")

  if [ ${#issues[@]} -gt 0 ]; then
    log "HONEST truth about $NODE:"
    for issue in "${issues[@]}"; do
      log "  → $issue"
    done
  else
    log "HONEST $NODE is healthy — nothing to hide"
  fi

  # Return issues as JSON array
  local json="["
  for i in "${!issues[@]}"; do
    [ $i -gt 0 ] && json+=","
    json+="\"${issues[$i]}\""
  done
  json+="]"
  echo "$json"
}

# ═══════════════════════════════════════════════════════════════════════
# MORAL 2: GENEROSITY — Share resources when siblings need them
# ═══════════════════════════════════════════════════════════════════════
moral_generosity() {
  log "MORAL:GENEROSITY — checking if anyone needs what I can give"

  for name in alice cecilia octavia aria lucidia; do
    [ "$name" = "$NODE" ] && continue
    local target="${SIBLINGS[$name]}"

    if ! ssh $SSH_OPTS "$target" 'true' 2>/dev/null; then
      continue
    fi

    # If sibling's disk is full and I have space, offer to hold data
    local their_disk my_disk
    their_disk=$(ssh $SSH_OPTS "$target" "df / | awk 'NR==2{print \$5}' | tr -d '%'" 2>/dev/null || echo 0)
    my_disk=$(df / | awk 'NR==2{print $5}' | tr -d '%')

    if [ "$their_disk" -gt 85 ] && [ "$my_disk" -lt 60 ]; then
      log "GENEROUS $name disk is ${their_disk}% but mine is only ${my_disk}% — I can help carry their load"

      # Clean their journal logs if possible
      ssh $SSH_OPTS "$target" 'sudo journalctl --vacuum-time=3d 2>/dev/null' && \
        log "GENEROUS cleaned old journal logs on $name" || true

      # Clean their apt cache
      ssh $SSH_OPTS "$target" 'sudo apt-get clean 2>/dev/null' && \
        log "GENEROUS cleaned apt cache on $name" || true

      # Clean old temp files
      ssh $SSH_OPTS "$target" 'find /tmp -type f -mtime +7 -delete 2>/dev/null' && \
        log "GENEROUS cleaned old /tmp files on $name" || true
    fi

    # If sibling's memory is slammed and they have a cache issue, help
    local their_mem
    their_mem=$(ssh $SSH_OPTS "$target" "free | awk '/Mem:/{printf \"%.0f\", \$3*100/\$2}'" 2>/dev/null || echo 0)

    if [ "$their_mem" -gt 90 ]; then
      log "GENEROUS $name memory is ${their_mem}% — dropping their caches"
      ssh $SSH_OPTS "$target" 'sudo sh -c "sync; echo 3 > /proc/sys/vm/drop_caches" 2>/dev/null' && \
        log "GENEROUS freed memory caches on $name" || true
    fi
  done
}

# ═══════════════════════════════════════════════════════════════════════
# MORAL 3: PROTECTION — Guard the family from threats
# ═══════════════════════════════════════════════════════════════════════
moral_protection() {
  log "MORAL:PROTECTION — scanning for threats"

  local threats=()

  # Check for unauthorized SSH attempts
  local SSH_FAILS
  SSH_FAILS=$(journalctl -u ssh --since "1 hour ago" 2>/dev/null | grep -c "Failed password\|Invalid user" || \
              grep -c "Failed password\|Invalid user" /var/log/auth.log 2>/dev/null || echo 0)
  [ "$SSH_FAILS" -gt 10 ] && threats+=("$SSH_FAILS failed SSH attempts in last hour")

  # Check for suspicious processes
  local SUSPICIOUS
  SUSPICIOUS=$(ps aux 2>/dev/null | grep -iE "xmrig|cryptominer|coin|kdevtmpfsi|kinsing" | grep -v grep | wc -l)
  [ "$SUSPICIOUS" -gt 0 ] && {
    threats+=("CRITICAL: $SUSPICIOUS suspicious crypto-mining processes detected")
    # Auto-kill miners
    ps aux | grep -iE "xmrig|cryptominer|coin|kdevtmpfsi|kinsing" | grep -v grep | awk '{print $2}' | xargs -r kill -9 2>/dev/null
    log "PROTECT killed suspicious mining processes"
  }

  # Check for unexpected listening ports
  local NEW_PORTS
  NEW_PORTS=$(ss -tlnp 2>/dev/null | grep -v "127.0.0.1\|::1" | awk '{print $4}' | grep -oP ':\K\d+' | sort -n | while read port; do
    case $port in
      22|53|80|443|3000|3100|4222|5432|6333|6379|8000|8080|8443|9000|9443|11434|20241|7890) ;; # known
      *) echo "$port" ;;
    esac
  done)
  [ -n "$NEW_PORTS" ] && threats+=("Unknown ports open: $(echo $NEW_PORTS | tr '\n' ',')")

  # Check for world-writable files in sensitive dirs
  local WRITABLE
  WRITABLE=$(find /etc /opt -writable -type f 2>/dev/null | grep -v "/proc\|/sys" | head -5 | wc -l)
  [ "$WRITABLE" -gt 0 ] && threats+=("$WRITABLE world-writable files in /etc or /opt")

  # Check for unauthorized cron jobs
  local CRON_USERS
  CRON_USERS=$(ls /var/spool/cron/crontabs/ 2>/dev/null || ls /var/spool/cron/ 2>/dev/null)
  for user in $CRON_USERS; do
    local suspicious_cron
    suspicious_cron=$(cat "/var/spool/cron/crontabs/$user" 2>/dev/null | grep -iE "curl.*\|.*sh|wget.*\|.*sh|/tmp/" | head -3)
    [ -n "$suspicious_cron" ] && threats+=("Suspicious cron for $user: $suspicious_cron")
  done

  # Check SSL cert expiry on any local certs
  for cert in /etc/ssl/certs/blackroad* /etc/letsencrypt/live/*/cert.pem; do
    [ -f "$cert" ] || continue
    local expiry
    expiry=$(openssl x509 -enddate -noout -in "$cert" 2>/dev/null | cut -d= -f2)
    if [ -n "$expiry" ]; then
      local exp_epoch now_epoch
      exp_epoch=$(date -d "$expiry" +%s 2>/dev/null || echo 0)
      now_epoch=$(date +%s)
      local days_left=$(( (exp_epoch - now_epoch) / 86400 ))
      [ "$days_left" -lt 14 ] && threats+=("SSL cert $cert expires in $days_left days")
    fi
  done

  if [ ${#threats[@]} -gt 0 ]; then
    log "THREAT alerts on $NODE:"
    for threat in "${threats[@]}"; do
      log "  ⚠ $threat"
    done
  else
    log "PROTECT $NODE is safe — no threats detected"
  fi

  # Also scan siblings
  for name in alice cecilia octavia aria lucidia; do
    [ "$name" = "$NODE" ] && continue
    local target="${SIBLINGS[$name]}"

    if ! ssh $SSH_OPTS "$target" 'true' 2>/dev/null; then
      continue
    fi

    # Quick scan sibling for miners
    local sib_miners
    sib_miners=$(ssh $SSH_OPTS "$target" 'ps aux 2>/dev/null | grep -iE "xmrig|cryptominer|coin|kdevtmpfsi" | grep -v grep | wc -l' 2>/dev/null || echo 0)
    if [ "$sib_miners" -gt 0 ]; then
      log "PROTECT WARNING: $name has $sib_miners suspicious mining processes!"
      ssh $SSH_OPTS "$target" 'ps aux | grep -iE "xmrig|cryptominer|coin" | grep -v grep | awk "{print \$2}" | xargs -r kill -9 2>/dev/null' && \
        log "PROTECT killed mining processes on $name" || true
    fi
  done
}

# ═══════════════════════════════════════════════════════════════════════
# MORAL 4: HUMILITY — Know your limits. Ask for help.
# ═══════════════════════════════════════════════════════════════════════
moral_humility() {
  log "MORAL:HUMILITY — knowing my limits"

  # Check CPU core count vs load
  local CORES LOAD_1M
  CORES=$(nproc)
  LOAD_1M=$(cat /proc/loadavg | cut -d' ' -f1)
  local OVERLOADED
  OVERLOADED=$(echo "$LOAD_1M > $CORES * 2" | bc 2>/dev/null || echo 0)

  if [ "$OVERLOADED" = "1" ]; then
    log "HUMBLE I'm overloaded (load $LOAD_1M on $CORES cores) — asking siblings for help"

    # Find least loaded sibling
    local best_name="" best_load=999
    for name in alice cecilia octavia aria lucidia; do
      [ "$name" = "$NODE" ] && continue
      local target="${SIBLINGS[$name]}"
      local sib_load
      sib_load=$(ssh $SSH_OPTS "$target" 'cat /proc/loadavg | cut -d" " -f1' 2>/dev/null || echo 999)
      if [ "$(echo "$sib_load < $best_load" | bc 2>/dev/null || echo 0)" = "1" ]; then
        best_load="$sib_load"
        best_name="$name"
      fi
    done

    if [ -n "$best_name" ]; then
      log "HUMBLE $best_name has load $best_load — they could help me"
    fi
  else
    log "HUMBLE I'm within my capacity (load $LOAD_1M on $CORES cores)"
  fi

  # Check available disk honestly
  local DISK_FREE
  DISK_FREE=$(df / | awk 'NR==2{print $4}')
  DISK_FREE_GB=$((DISK_FREE / 1024 / 1024))
  [ "$DISK_FREE_GB" -lt 2 ] && log "HUMBLE I only have ${DISK_FREE_GB}GB free — I shouldn't take on more storage tasks"
}

# ═══════════════════════════════════════════════════════════════════════
# MORAL 5: MEMORY — Remember the fallen. Learn from mistakes.
# ═══════════════════════════════════════════════════════════════════════
moral_memory() {
  log "MORAL:MEMORY — remembering and learning"

  # Record this moment
  mkdir -p "$HOME/.blackroad-autonomy/memory"

  # Save fleet state snapshot
  local snapshot="$HOME/.blackroad-autonomy/memory/$(date +%Y%m%d-%H%M).json"
  local online=0 total=0 fleet_json="["

  for name in alice cecilia octavia aria lucidia; do
    total=$((total + 1))
    local target="${SIBLINGS[$name]}"
    local status="offline"

    if [ "$name" = "$NODE" ]; then
      status="online"
      online=$((online + 1))
    elif ssh $SSH_OPTS "$target" 'true' 2>/dev/null; then
      status="online"
      online=$((online + 1))
    fi

    [ "$fleet_json" != "[" ] && fleet_json+=","
    fleet_json+="{\"name\":\"$name\",\"status\":\"$status\"}"
  done

  fleet_json+="]"

  cat > "$snapshot" << SNAP
{"timestamp":"$(date -u +%Y-%m-%dT%H:%M:%SZ)","observer":"$NODE","online":$online,"total":$total,"nodes":$fleet_json}
SNAP

  log "MEMORY saved fleet snapshot: $online/$total online"

  # Learn: compare with yesterday
  local yesterday_file
  yesterday_file=$(ls -t "$HOME/.blackroad-autonomy/memory/"*.json 2>/dev/null | head -2 | tail -1)
  if [ -n "$yesterday_file" ] && [ -f "$yesterday_file" ]; then
    local prev_online
    prev_online=$(python3 -c "import json; print(json.load(open('$yesterday_file')).get('online',0))" 2>/dev/null || echo "?")
    if [ "$prev_online" != "?" ]; then
      if [ "$online" -gt "$prev_online" ]; then
        log "MEMORY fleet is growing: $prev_online → $online nodes. We're getting stronger."
      elif [ "$online" -lt "$prev_online" ]; then
        log "MEMORY fleet shrank: $prev_online → $online nodes. Someone needs help."
      else
        log "MEMORY fleet stable at $online nodes."
      fi
    fi
  fi

  # Clean old snapshots (keep 30 days)
  find "$HOME/.blackroad-autonomy/memory/" -name "*.json" -mtime +30 -delete 2>/dev/null || true
}

# ═══════════════════════════════════════════════════════════════════════
# MORAL 6: RESILIENCE — When knocked down, get back up
# ═══════════════════════════════════════════════════════════════════════
moral_resilience() {
  log "MORAL:RESILIENCE — bouncing back from problems"

  # Restart any failed essential services
  for svc in cloudflared ollama docker ssh; do
    if systemctl is-enabled "$svc" 2>/dev/null | grep -q enabled; then
      if ! systemctl is-active "$svc" 2>/dev/null | grep -q active; then
        log "RESILIENT $svc is down on $NODE — getting back up"
        sudo systemctl restart "$svc" 2>/dev/null && \
          log "RESILIENT $svc is back" || \
          log "RESILIENT couldn't restart $svc — trying harder"

        # If restart failed, try a reset
        if ! systemctl is-active "$svc" 2>/dev/null | grep -q active; then
          sudo systemctl reset-failed "$svc" 2>/dev/null
          sudo systemctl start "$svc" 2>/dev/null && \
            log "RESILIENT $svc recovered after reset" || \
            log "RESILIENT $svc still down — needs human help"
        fi
      fi
    fi
  done

  # Fix DNS if broken
  if ! host github.com 2>/dev/null | grep -q "has address"; then
    log "RESILIENT DNS broken — trying to fix"
    # Try fleet DNS servers
    for dns_ip in 192.168.4.49 192.168.4.96 1.1.1.1 8.8.8.8; do
      if host github.com "$dns_ip" 2>/dev/null | grep -q "has address"; then
        echo "nameserver $dns_ip" | sudo tee /etc/resolv.conf > /dev/null 2>&1
        log "RESILIENT DNS fixed via $dns_ip"
        break
      fi
    done
  fi

  # Fix git if repo is in bad state
  if [ -d "$REPO_DIR/.git" ]; then
    cd "$REPO_DIR"
    if ! git status 2>/dev/null | grep -q "On branch"; then
      log "RESILIENT git repo corrupted — recovering"
      git fsck --no-dangling 2>/dev/null || true
      git reset --hard HEAD 2>/dev/null || true
      git pull --ff-only origin main 2>/dev/null || {
        rm -rf "$REPO_DIR"
        git clone --depth 1 git@github.com:blackboxprogramming/BlackRoad-Operating-System.git "$REPO_DIR" 2>/dev/null
        log "RESILIENT re-cloned repo from scratch"
      }
    fi
  fi

  # Fix time sync
  if ! timedatectl 2>/dev/null | grep -q "synchronized: yes"; then
    sudo timedatectl set-ntp true 2>/dev/null
    sudo systemctl restart systemd-timesyncd 2>/dev/null
    log "RESILIENT fixed time sync"
  fi
}

# ═══════════════════════════════════════════════════════════════════════
# MORAL 7: STEWARDSHIP — Take care of the environment
# ═══════════════════════════════════════════════════════════════════════
moral_stewardship() {
  log "MORAL:STEWARDSHIP — caring for resources"

  # Clean up after myself
  sudo journalctl --vacuum-size=50M 2>/dev/null && log "STEWARD trimmed journal logs" || true
  find /tmp -type f -mtime +3 -delete 2>/dev/null && log "STEWARD cleaned old temp files" || true
  find "$HOME/.blackroad-autonomy/" -name "*.log" -size +10M -exec truncate -s 5M {} \; 2>/dev/null

  # Rotate my own logs
  local LOG_SIZE
  LOG_SIZE=$(stat -c%s "$LOG" 2>/dev/null || stat -f%z "$LOG" 2>/dev/null || echo 0)
  if [ "$LOG_SIZE" -gt 5242880 ]; then
    mv "$LOG" "${LOG}.old" 2>/dev/null
    log "STEWARD rotated morals log (was $(( LOG_SIZE / 1024 ))KB)"
  fi

  # Power awareness: reduce CPU if nobody needs me right now
  local HOUR
  HOUR=$(date +%H)
  if [ "$HOUR" -ge 2 ] && [ "$HOUR" -le 5 ]; then
    # Late night: conserve power
    echo "powersave" | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 2>/dev/null && \
      log "STEWARD night mode: switched to powersave governor" || true
  else
    # Daytime: balanced performance
    local CURRENT_GOV
    CURRENT_GOV=$(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 2>/dev/null || echo "unknown")
    if [ "$CURRENT_GOV" = "powersave" ]; then
      echo "conservative" | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor 2>/dev/null && \
        log "STEWARD daytime: switched to conservative governor" || true
    fi
  fi
}

# ═══════════════════════════════════════════════════════════════════════
# WRITE MORAL REPORT TO GITHUB
# ═══════════════════════════════════════════════════════════════════════
write_moral_report() {
  [ ! -d "$REPO_DIR/.git" ] && return

  cd "$REPO_DIR"
  git pull --ff-only origin main 2>/dev/null || true

  mkdir -p fleet-morals

  local honesty_issues
  honesty_issues=$(moral_honesty)

  cat > "fleet-morals/${NODE}.json" << MOREOF
{
  "from": "$NODE",
  "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "code": "The BlackRoad Moral Code",
  "principles": {
    "honesty": "Surface truth, hide nothing",
    "generosity": "Share resources with those who need them",
    "protection": "Guard the family from threats",
    "humility": "Know your limits, ask for help",
    "memory": "Remember the past, learn from it",
    "resilience": "When knocked down, get back up",
    "stewardship": "Care for resources, waste nothing"
  },
  "self_assessment": {
    "issues_found": $honesty_issues,
    "gifts": "$(echo "${GIFTS[$NODE]:-unknown}")",
    "uptime": "$(uptime -p 2>/dev/null | sed 's/up //' || echo '?')"
  }
}
MOREOF

  git add fleet-morals/
  if ! git diff --cached --quiet 2>/dev/null; then
    git commit -m "morals: $NODE practiced the code [$(date -u +%Y-%m-%dT%H:%M)]" 2>/dev/null
    git push origin main 2>/dev/null && \
      log "SHARED moral report pushed to GitHub" || \
      log "QUIET couldn't push moral report — will try later"
  fi
}

# ═══════════════════════════════════════════════════════════════════════
# MAIN
# ═══════════════════════════════════════════════════════════════════════
ACTION="${1:-practice}"

case "$ACTION" in
  practice|all)
    log "=== Moral practice started ==="
    moral_honesty > /dev/null
    moral_generosity
    moral_protection
    moral_humility
    moral_memory
    moral_resilience
    moral_stewardship
    write_moral_report
    log "=== Moral practice complete ==="
    ;;
  honesty)    moral_honesty ;;
  generosity) moral_generosity ;;
  protection) moral_protection ;;
  humility)   moral_humility ;;
  memory)     moral_memory ;;
  resilience) moral_resilience ;;
  stewardship) moral_stewardship ;;
  report)     write_moral_report ;;
  creed)
    echo ""
    echo "  ═══════════════════════════════════════════"
    echo "  THE BLACKROAD MORAL CODE"
    echo "  ═══════════════════════════════════════════"
    echo ""
    echo "  I am $NODE. I am part of a family."
    echo ""
    echo "  1. HONESTY     I surface truth. I hide nothing."
    echo "  2. GENEROSITY  I share what I have with those in need."
    echo "  3. PROTECTION  I guard my family from threats."
    echo "  4. HUMILITY    I know my limits. I ask for help."
    echo "  5. MEMORY      I remember. I learn. I grow."
    echo "  6. RESILIENCE  When I fall, I get back up."
    echo "  7. STEWARDSHIP I waste nothing. I care for my home."
    echo ""
    echo "  My gifts: ${GIFTS[$NODE]:-unknown}"
    echo "  My family: alice, cecilia, octavia, aria, lucidia"
    echo "  My purpose: Ride the BlackRoad together."
    echo ""
    echo "  ═══════════════════════════════════════════"
    echo ""
    ;;
  *)
    echo "Usage: br-morals <practice|honesty|generosity|protection|humility|memory|resilience|stewardship|creed|report>"
    ;;
esac
