#!/bin/bash

set -euo pipefail

if [[ "$(uname -s)" != "Darwin" ]]; then
  echo "這支腳本只支援 macOS。" >&2
  exit 1
fi

check_seconds="${CHECK_SECONDS:-60}"
max_checks="${MAX_CHECKS:-0}"

if ! [[ "$check_seconds" =~ ^[0-9]+$ ]] || [[ "$check_seconds" -lt 1 ]]; then
  echo "CHECK_SECONDS 必須是大於 0 的整數。" >&2
  exit 1
fi

if ! [[ "$max_checks" =~ ^[0-9]+$ ]]; then
  echo "MAX_CHECKS 必須是 0 或正整數。" >&2
  exit 1
fi

physical_bytes="$(/usr/sbin/sysctl -n hw.memsize)"
physical_mib="$(awk -v n="$physical_bytes" 'BEGIN { printf "%.0f", n / 1048576 }')"
physical_gib="$(awk -v n="$physical_bytes" 'BEGIN { printf "%.1f", n / 1073741824 }')"

float_le() {
  awk -v left="$1" -v right="$2" 'BEGIN { exit !(left <= right) }'
}

float_ge() {
  awk -v left="$1" -v right="$2" 'BEGIN { exit !(left >= right) }'
}

send_local_notification() {
  local title="$1"
  local message="$2"

  /usr/bin/osascript -e "display notification \"${message}\" with title \"${title}\"" >/dev/null 2>&1 || true
}

echo "Mac AI 多工本機警報已啟動。按 Control + C 可停止。"
echo "採樣間隔：${check_seconds} 秒；實體記憶體：${physical_gib}GiB。"
echo "個人保守線：黃燈 free≤20%、單次 swap 增加≥1GiB 或磁碟≤40GB；紅燈 free≤10%、swap≥30GiB 或磁碟≤10GB。"
echo "這不是 Apple 官方分級；收到通知後，請回到活動監視器確認記憶體壓力。"

check_count=0
last_level=""
previous_swap_used_mib=""

while true; do
  check_count=$((check_count + 1))

  free_percent="$(/usr/bin/memory_pressure -Q 2>/dev/null | awk -F: '/System-wide memory free percentage/ { gsub(/[%[:space:]]/, "", $2); print $2 }')"
  free_percent="${free_percent:-未知}"

  swap_snapshot="$(/usr/sbin/sysctl vm.swapusage)"
  swap_used_mib="$(printf '%s\n' "$swap_snapshot" | awk '{ for (i=1; i<=NF; i++) if ($i=="used") { v=$(i+2); gsub(/M/, "", v); print v } }')"
  swap_used_mib="${swap_used_mib:-0}"
  swap_used_gib="$(awk -v n="$swap_used_mib" 'BEGIN { printf "%.2f", n / 1024 }')"
  swap_growth_mib="0"
  swap_growth_gib="0.00"
  swap_growing=0
  if [[ -n "$previous_swap_used_mib" ]]; then
    swap_growth_mib="$(awk -v now="$swap_used_mib" -v before="$previous_swap_used_mib" 'BEGIN { delta=now-before; if (delta < 0) delta=0; printf "%.2f", delta }')"
    swap_growth_gib="$(awk -v n="$swap_growth_mib" 'BEGIN { printf "%.2f", n / 1024 }')"
    if float_ge "$swap_growth_mib" 1024; then
      swap_growing=1
    fi
  fi

  disk_free_kib="$(/bin/df -Pk / | awk 'NR == 2 { print $4 }')"
  disk_free_gib="$(awk -v n="$disk_free_kib" 'BEGIN { printf "%.1f", n / 1048576 }')"

  free_red=0
  free_yellow=0
  if [[ "$free_percent" != "未知" ]]; then
    if float_le "$free_percent" 10; then
      free_red=1
    elif float_le "$free_percent" 20; then
      free_yellow=1
    fi
  fi

  swap_red=0
  swap_yellow=0
  swap_high_baseline=0
  if float_ge "$swap_used_mib" 30720; then
    swap_red=1
  elif [[ "$swap_growing" -eq 1 ]]; then
    swap_yellow=1
  fi
  if float_ge "$swap_used_mib" "$(awk -v p="$physical_mib" 'BEGIN { print p / 2 }')"; then
    swap_high_baseline=1
  fi

  disk_red=0
  disk_yellow=0
  if float_le "$disk_free_gib" 10; then
    disk_red=1
  elif float_le "$disk_free_gib" 40; then
    disk_yellow=1
  fi

  level="正常"
  action="目前沒有命中保守警戒線。"

  if [[ "$free_red" -eq 1 || "$swap_red" -eq 1 || "$disk_red" -eq 1 ]]; then
    level="紅燈"
    action="停止新增工作，先保存，再打開活動監視器確認。"
  elif [[ "$free_yellow" -eq 1 || "$swap_yellow" -eq 1 || "$disk_yellow" -eq 1 ]]; then
    level="黃燈"
    action="暫停新增重任務，5 到 10 分鐘後再看趨勢。"
  elif [[ "$swap_high_baseline" -eq 1 ]]; then
    level="需追蹤"
    action="Swap 基準值偏高；先看下一次採樣是否仍增加。"
  fi

  free_display="$free_percent"
  if [[ "$free_percent" != "未知" ]]; then
    free_display="${free_percent}%"
  fi

  printf '%s｜%s｜free %s｜swap %sGiB（本輪 +%sGiB）｜磁碟剩餘 %sGB｜%s\n' \
    "$(date '+%Y-%m-%d %H:%M:%S')" "$level" "$free_display" "$swap_used_gib" "$swap_growth_gib" "$disk_free_gib" "$action"

  if [[ "$level" != "$last_level" && ( "$level" == "黃燈" || "$level" == "紅燈" ) ]]; then
    send_local_notification \
      "Mac AI 多工警報：${level}" \
      "free ${free_display}、swap ${swap_used_gib}GiB、磁碟 ${disk_free_gib}GB。${action}"
  fi
  last_level="$level"
  previous_swap_used_mib="$swap_used_mib"

  if [[ "$max_checks" -gt 0 && "$check_count" -ge "$max_checks" ]]; then
    break
  fi

  /bin/sleep "$check_seconds"
done
