#!/bin/bash
# YuSu 診斷腳本 - 用於排查安裝問題（含「包損壞」檢測）
# 使用方法: bash debug.sh

# 顏色定義
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

APP="$HOME/Library/Input Methods/YuSu.app"
USER_DIR="$HOME/Library/YuSu"
REPORT=""

# 添加到報告
add_report() {
  REPORT+="$1"$'\n'
}

# 帶顏色輸出並記錄
log_ok() {
  echo -e "${GREEN}✓${NC} $1"
  add_report "✓ $1"
}

log_err() {
  echo -e "${RED}✗${NC} $1"
  add_report "✗ $1"
}

log_warn() {
  echo -e "${YELLOW}○${NC} $1"
  add_report "○ $1"
}

log_info() {
  echo "$1"
  add_report "$1"
}

section() {
  echo ""
  echo -e "${YELLOW}=== $1 ===${NC}"
  add_report ""
  add_report "------------------------------"
  add_report "$1"
  add_report "------------------------------"
}

# 開始診斷
echo ""
echo "╔══════════════════════════════════════════╗"
echo "║       YuSu 診斷腳本 v1.0                  ║"
echo "║   檢測「包損壞」及安裝問題                 ║"
echo "╚══════════════════════════════════════════╝"
echo ""

add_report "YuSu 診斷報告"
add_report "生成時間: $(date '+%Y-%m-%d %H:%M:%S')"
add_report "============================================"

# 1. 系統信息
section "1. 系統信息"
OS_VER=$(sw_vers -productVersion)
OS_BUILD=$(sw_vers -buildVersion)
ARCH=$(uname -m)
log_info "macOS 版本: $OS_VER ($OS_BUILD)"
log_info "系統架構: $ARCH"

# 2. App 基本檢查
section "2. App 文件檢查"
if [ -d "$APP" ]; then
  log_ok "App 存在: $APP"

  BUNDLE_ID=$(defaults read "$APP/Contents/Info.plist" CFBundleIdentifier 2>/dev/null)
  VERSION=$(defaults read "$APP/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null)
  MIN_OS=$(defaults read "$APP/Contents/Info.plist" LSMinimumSystemVersion 2>/dev/null)

  log_info "Bundle ID: $BUNDLE_ID"
  log_info "版本: $VERSION"
  log_info "最低 macOS: $MIN_OS"

  # 檢查二進制文件
  BINARY="$APP/Contents/MacOS/YuSu"
  if [ -f "$BINARY" ]; then
    BINARY_SIZE=$(du -h "$BINARY" | cut -f1)
    log_ok "二進制文件存在 ($BINARY_SIZE)"
  else
    log_err "二進制文件不存在！"
  fi
else
  log_err "App 不存在: $APP"
  log_info "請先安裝 YuSu 輸入法"
fi

# 3. 關鍵：代碼簽名檢查（包損壞的主要原因）
section "3. 代碼簽名檢查（關鍵）"
if [ -d "$APP" ]; then
  # 驗證簽名
  CODESIGN_RESULT=$(codesign -v "$APP" 2>&1)
  if [ $? -eq 0 ]; then
    log_ok "代碼簽名有效"
  else
    log_err "代碼簽名無效！"
    log_info "錯誤: $CODESIGN_RESULT"
  fi

  # 獲取簽名詳情
  SIGN_INFO=$(codesign -dv "$APP" 2>&1)
  TEAM_ID=$(echo "$SIGN_INFO" | grep "TeamIdentifier" | cut -d= -f2)
  if [ -n "$TEAM_ID" ] && [ "$TEAM_ID" != "not set" ]; then
    log_ok "Team ID: $TEAM_ID"
  else
    log_warn "未找到 Team ID（可能是自簽名）"
  fi

  # 檢查簽名類型
  if echo "$SIGN_INFO" | grep -q "Developer ID"; then
    log_ok "簽名類型: Developer ID（正式發布）"
  elif echo "$SIGN_INFO" | grep -q "Apple Development"; then
    log_warn "簽名類型: 開發者簽名（非正式發布）"
  else
    log_warn "簽名類型: 未知"
  fi
fi

# 4. Gatekeeper / Notarization 檢查
section "4. Gatekeeper 檢查"
if [ -d "$APP" ]; then
  SPCTL_RESULT=$(spctl -a -vvv -t install "$APP" 2>&1)

  if echo "$SPCTL_RESULT" | grep -q "accepted"; then
    log_ok "Gatekeeper 已接受此 App"

    if echo "$SPCTL_RESULT" | grep -qi "notarized"; then
      log_ok "App 已公證 (Notarized)"
    else
      log_warn "App 未公證（可能導致包損壞提示）"
    fi
  else
    log_err "Gatekeeper 拒絕此 App！"
    log_info "詳情: $(echo "$SPCTL_RESULT" | head -3)"
  fi

  # 顯示來源
  SOURCE=$(echo "$SPCTL_RESULT" | grep "source=" | head -1)
  if [ -n "$SOURCE" ]; then
    log_info "來源: $SOURCE"
  fi
fi

# 5. 隔離屬性檢查（com.apple.quarantine）
section "5. 隔離屬性檢查"
if [ -d "$APP" ]; then
  QUARANTINE=$(xattr -l "$APP" 2>/dev/null | grep "com.apple.quarantine")

  if [ -n "$QUARANTINE" ]; then
    log_warn "存在隔離屬性（可能導致問題）"
    log_info "屬性值: $QUARANTINE"
    log_info "修復方法: xattr -cr \"$APP\""
  else
    log_ok "無隔離屬性"
  fi

  # 檢查所有擴展屬性
  ALL_XATTR=$(xattr "$APP" 2>/dev/null)
  if [ -n "$ALL_XATTR" ]; then
    log_info "所有擴展屬性:"
    while IFS= read -r attr; do
      log_info "  - $attr"
    done <<< "$ALL_XATTR"
  fi
fi

# 6. Frameworks 和依賴庫檢查
section "6. Frameworks 檢查"
FW="$APP/Contents/Frameworks"
if [ -d "$FW" ]; then
  log_ok "Frameworks 目錄存在"

  # 檢查 libyime.dylib
  DYLIB="$FW/libyime.dylib"
  if [ -f "$DYLIB" ]; then
    DYLIB_SIZE=$(du -h "$DYLIB" | cut -f1)
    log_ok "libyime.dylib 存在 ($DYLIB_SIZE)"

    # 檢查 dylib 簽名
    DYLIB_SIGN=$(codesign -v "$DYLIB" 2>&1)
    if [ $? -eq 0 ]; then
      log_ok "libyime.dylib 簽名有效"
    else
      log_err "libyime.dylib 簽名無效！"
    fi
  else
    log_err "libyime.dylib 不存在！"
  fi

  # 檢查 Sparkle
  if [ -d "$FW/Sparkle.framework" ]; then
    log_ok "Sparkle.framework 存在"
  fi
else
  log_err "Frameworks 目錄不存在！"
fi

# 7. 輸入法註冊狀態
section "7. 輸入法註冊狀態"
LSREGISTER="/System/Library/Frameworks/CoreServices.framework/Versions/Current/Frameworks/LaunchServices.framework/Versions/Current/Support/lsregister"
REG_COUNT=$("$LSREGISTER" -dump 2>/dev/null | grep -c "app.inputmethod.yusu")
if [ "$REG_COUNT" -gt 0 ]; then
  log_ok "已在系統註冊 ($REG_COUNT 條記錄)"
else
  log_warn "未在系統註冊"
  log_info "修復方法: $LSREGISTER -f \"$APP\""
fi

# 檢查 TIS 輸入法列表（是否在系統輸入法菜單中可用）
TIS_CHECK=$(defaults read com.apple.HIToolbox AppleEnabledInputSources 2>/dev/null | grep -c "yusu")
if [ "$TIS_CHECK" -gt 0 ]; then
  log_ok "已添加到系統輸入法列表"
else
  log_warn "未添加到系統輸入法列表（需要在系統設置中添加）"
fi

# 檢查輸入法是否在可選列表中（灰色不可選問題診斷）
BUNDLE_ID="app.inputmethod.yusu"
TIS_AVAILABLE=$("$LSREGISTER" -dump 2>/dev/null | grep -A 10 "$BUNDLE_ID" | grep -i "claim" | head -1)
if [ -n "$TIS_AVAILABLE" ]; then
  log_info "TIS Claim: $TIS_AVAILABLE"
fi

# 檢查 Info.plist 中的輸入法配置
if [ -f "$APP/Contents/Info.plist" ]; then
  IM_MODE=$(defaults read "$APP/Contents/Info.plist" LSBackgroundOnly 2>/dev/null)
  if [ "$IM_MODE" = "1" ]; then
    log_ok "LSBackgroundOnly = 1（正確）"
  else
    log_warn "LSBackgroundOnly 未設置或不正確"
  fi

  TISM_INPUT=$(defaults read "$APP/Contents/Info.plist" tsInputModeListKey 2>/dev/null)
  if [ -n "$TISM_INPUT" ]; then
    log_ok "tsInputModeListKey 已配置"
  else
    log_err "tsInputModeListKey 未配置（可能導致無法選擇）"
  fi
fi

# 8. 進程狀態
section "8. 進程狀態"
YUSU_PROCS=$(pgrep -f "YuSu" 2>/dev/null)
if [ -n "$YUSU_PROCS" ]; then
  log_ok "YuSu 進程運行中"
  ps aux | grep -i "[Y]uSu" | while read line; do
    log_info "  $line"
  done
else
  log_warn "YuSu 進程未運行"
fi

# 9. YuSuPet 桌面寵物檢查
section "9. YuSuPet 桌面寵物"
# YuSuPet 現在位於 SharedSupport，隨主程序一起更新
PET_APP="$APP/Contents/SharedSupport/YuSuPet.app"
if [ -d "$PET_APP" ]; then
  log_ok "YuSuPet.app 存在"

  # 檢查版本
  PET_VERSION=$(defaults read "$PET_APP/Contents/Info.plist" CFBundleShortVersionString 2>/dev/null)
  log_info "版本: $PET_VERSION"

  # 檢查二進制文件架構
  PET_BINARY="$PET_APP/Contents/MacOS/YuSuPet"
  if [ -f "$PET_BINARY" ]; then
    PET_ARCHS=$(lipo -archs "$PET_BINARY" 2>/dev/null)
    log_info "支持架構: $PET_ARCHS"

    # 檢查是否支持當前架構
    if echo "$PET_ARCHS" | grep -q "$ARCH"; then
      log_ok "支持當前系統架構 ($ARCH)"
    else
      log_err "不支持當前系統架構！(需要 $ARCH，實際 $PET_ARCHS)"
    fi

    # 檢查簽名
    PET_SIGN=$(codesign -v "$PET_APP" 2>&1)
    if [ $? -eq 0 ]; then
      log_ok "代碼簽名有效"
    else
      log_warn "代碼簽名無效: $PET_SIGN"
    fi
  else
    log_err "YuSuPet 二進制文件不存在！"
  fi
else
  log_warn "YuSuPet.app 未打包（趣味效果不可用）"
fi

# 清理提示：舊位置的 YuSuPet
OLD_PET="$HOME/Library/Application Support/YuSu/YuSuPet.app"
if [ -d "$OLD_PET" ]; then
  log_warn "發現舊位置的 YuSuPet，建議刪除: $OLD_PET"
fi

# 10. 用戶配置目錄
section "10. 用戶配置目錄"
if [ -d "$USER_DIR" ]; then
  FILE_COUNT=$(find "$USER_DIR" -type f 2>/dev/null | wc -l | tr -d ' ')
  log_ok "配置目錄存在 ($FILE_COUNT 個文件)"

  # 檢查 build 目錄
  if [ -d "$USER_DIR/build" ]; then
    BIN_COUNT=$(ls "$USER_DIR/build/"*.bin 2>/dev/null | wc -l | tr -d ' ')
    log_info "詞庫文件: $BIN_COUNT 個"

    # 檢測詞庫文件有效性（通過 magic header 驗證）
    CORRUPT_COUNT=0
    for binfile in "$USER_DIR/build/"*.bin; do
      [ -f "$binfile" ] || continue
      FILENAME=$(basename "$binfile")
      FILESIZE=$(stat -f%z "$binfile" 2>/dev/null || echo 0)

      # 檢查文件大小
      if [ "$FILESIZE" -eq 0 ]; then
        log_err "損壞: $FILENAME (大小為 0)"
        CORRUPT_COUNT=$((CORRUPT_COUNT + 1))
        continue
      fi

      # 檢查 magic header
      HEADER=$(head -c 16 "$binfile" 2>/dev/null | strings 2>/dev/null | head -1)
      case "$FILENAME" in
        *.prism.bin)
          if ! echo "$HEADER" | grep -q "Rime::Prism"; then
            log_err "損壞: $FILENAME (無效的 prism 格式)"
            CORRUPT_COUNT=$((CORRUPT_COUNT + 1))
          fi
          ;;
        *.table.bin)
          if ! echo "$HEADER" | grep -q "Rime::Table"; then
            log_err "損壞: $FILENAME (無效的 table 格式)"
            CORRUPT_COUNT=$((CORRUPT_COUNT + 1))
          fi
          ;;
        *.reverse.bin)
          if ! echo "$HEADER" | grep -q "Rime::Reverse"; then
            log_err "損壞: $FILENAME (無效的 reverse 格式)"
            CORRUPT_COUNT=$((CORRUPT_COUNT + 1))
          fi
          ;;
      esac
    done

    if [ "$CORRUPT_COUNT" -eq 0 ]; then
      log_ok "詞庫文件格式驗證通過"
    else
      log_err "發現 $CORRUPT_COUNT 個損壞的詞庫文件"
      log_info "修復方法: 刪除 $USER_DIR/build/.ok 後重新切換輸入法"
    fi

    # 檢查 .ok 標記文件（編譯完整性標記）
    OK_FILE="$USER_DIR/build/.ok"
    if [ -f "$OK_FILE" ]; then
      OK_CONTENT=$(cat "$OK_FILE" 2>/dev/null)
      log_ok "編譯標記存在: $OK_CONTENT"

      # 比對 App 版本
      if [ -n "$VERSION" ]; then
        APP_BUILD=$(defaults read "$APP/Contents/Info.plist" CFBundleVersion 2>/dev/null)
        EXPECTED_OK="$VERSION.$APP_BUILD"
        if [ "$OK_CONTENT" = "$EXPECTED_OK" ]; then
          log_ok "編譯標記版本匹配"
        else
          log_warn "編譯標記版本不匹配（標記: $OK_CONTENT, App: $EXPECTED_OK）"
          log_info "下次切換輸入法會自動重編譯"
        fi
      fi
    else
      log_warn "編譯標記不存在（可能編譯未完成或被中斷）"
      log_info "下次切換輸入法會自動重編譯"
    fi
  fi
else
  log_warn "配置目錄不存在（首次啟動會自動創建）"
fi

# 11. Legacy 文件檢查
section "11. Legacy 文件檢查"
LEGACY_COUNT=0

# 舊版 YuSu.localized
if [ -d "$HOME/Library/Input Methods/YuSu.localized" ]; then
  log_warn "發現舊版: YuSu.localized"
  LEGACY_COUNT=$((LEGACY_COUNT + 1))
fi

# 舊版 Bundle ID 的緩存和配置
if [ -d "$HOME/Library/Caches/safex.inputmethod.yusu" ]; then
  log_warn "發現舊版緩存: safex.inputmethod.yusu"
  LEGACY_COUNT=$((LEGACY_COUNT + 1))
fi
if [ -f "$HOME/Library/Preferences/safex.inputmethod.yusu.plist" ]; then
  log_warn "發現舊版配置: safex.inputmethod.yusu.plist"
  LEGACY_COUNT=$((LEGACY_COUNT + 1))
fi

# KeyKey 輸入法殘留
if [ -d "$HOME/Library/Input Methods/KeyKey.app" ]; then
  log_warn "發現殘留: KeyKey.app (用戶級)"
  LEGACY_COUNT=$((LEGACY_COUNT + 1))
fi
if [ -d "$HOME/Library/KeyKey" ]; then
  log_warn "發現殘留: KeyKey 配置目錄"
  LEGACY_COUNT=$((LEGACY_COUNT + 1))
fi

# 系統級安裝（需要管理員權限刪除）
if [ -d "/Library/Input Methods/YuSu.app" ]; then
  log_warn "發現系統級安裝: /Library/Input Methods/YuSu.app"
  LEGACY_COUNT=$((LEGACY_COUNT + 1))
fi
if [ -d "/Library/Input Methods/KeyKey.app" ]; then
  log_warn "發現系統級安裝: /Library/Input Methods/KeyKey.app"
  LEGACY_COUNT=$((LEGACY_COUNT + 1))
fi

if [ "$LEGACY_COUNT" -eq 0 ]; then
  log_ok "無 Legacy 文件"
else
  log_info "發現 $LEGACY_COUNT 個 Legacy 文件，建議使用卸載腳本清理"
fi

# 12. Crash Log 檢查
section "12. Crash Log 檢查"
CRASH_DIR="$HOME/Library/Logs/DiagnosticReports"
CRASH_COUNT=0

# 查找最近 7 天內的 YuSu 相關 crash log
if [ -d "$CRASH_DIR" ]; then
  # 查找 YuSu 相關的 crash 文件（.ips 或 .crash）
  CRASH_FILES=$(find "$CRASH_DIR" -name "*YuSu*" -o -name "*yusu*" -mtime -7 2>/dev/null | head -5)

  if [ -n "$CRASH_FILES" ]; then
    CRASH_COUNT=$(echo "$CRASH_FILES" | wc -l | tr -d ' ')
    log_warn "發現 $CRASH_COUNT 個近期 Crash 報告"

    # 添加最近一個 crash log 的摘要
    LATEST_CRASH=$(echo "$CRASH_FILES" | head -1)
    if [ -f "$LATEST_CRASH" ]; then
      log_info "最近 Crash: $(basename "$LATEST_CRASH")"

      # 提取 crash 摘要（前 50 行）
      add_report ""
      add_report "--- 最近 Crash Log 摘要 ---"
      head -50 "$LATEST_CRASH" | while IFS= read -r line; do
        add_report "$line"
      done
      add_report "--- Crash Log 摘要結束 ---"
    fi
  else
    log_ok "無近期 Crash 報告"
  fi
else
  log_info "Crash 目錄不存在"
fi

# 13. 診斷總結
section "13. 診斷總結"

# 統計問題
ERR_COUNT=$(echo "$REPORT" | grep -c "^✗")
WARN_COUNT=$(echo "$REPORT" | grep -c "^○")

if [ "$ERR_COUNT" -eq 0 ] && [ "$WARN_COUNT" -eq 0 ]; then
  log_ok "未發現問題，系統狀態良好"
elif [ "$ERR_COUNT" -eq 0 ]; then
  log_warn "發現 $WARN_COUNT 個警告，建議關注"
else
  log_err "發現 $ERR_COUNT 個錯誤，$WARN_COUNT 個警告"
  echo ""
  echo -e "${RED}常見修復方法：${NC}"
  echo "1. 清除隔離屬性: xattr -cr \"$APP\""
  echo "2. 重新註冊: $LSREGISTER -f \"$APP\""
  echo "3. 在「系統設置 > 隱私與安全性」中允許打開"
fi

add_report ""
add_report "錯誤數: $ERR_COUNT"
add_report "警告數: $WARN_COUNT"

# 用戶選項
echo ""
echo "╔══════════════════════════════════════════╗"
echo "║           請選擇下一步操作               ║"
echo "╠══════════════════════════════════════════╣"
echo "║  1. 發送診斷報告給開發者                 ║"
echo "║  2. 保存診斷報告到文件                   ║"
echo "║  0. 取消並退出                           ║"
echo "╚══════════════════════════════════════════╝"
echo ""
read -p "請輸入選項 [0-2]: " CHOICE

case $CHOICE in
  1)
    echo ""
    echo "正在發送診斷報告..."

    # 使用 base64 編碼避免特殊字符問題
    B64_CONTENT=$(echo "$REPORT" | base64 | tr -d '\n')

    # 發送到 BE（content 字段使用 base64 編碼）
    RESPONSE=$(curl -s -X POST "https://safex.cloud/ticket" \
      -H "Content-Type: application/json" \
      -d "{\"app\":\"yusu\",\"category\":\"bug\",\"title\":\"診斷報告: macOS $OS_VER\",\"content\":\"$B64_CONTENT\"}")

    if echo "$RESPONSE" | grep -q '"_res":"ok"'; then
      echo -e "${GREEN}✓ 診斷報告已成功發送！${NC}"
      echo "開發者將盡快查看並處理，感謝您的反饋。"
    else
      echo -e "${RED}✗ 發送失敗${NC}"
      echo "錯誤: $RESPONSE"
      echo ""
      echo "請手動保存報告（選項 2）並通過其他方式聯繫開發者。"
    fi
    ;;

  2)
    # 保存到腳本所在目錄
    SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
    REPORT_FILE="$SCRIPT_DIR/yusu_diag_$(date +%Y%m%d_%H%M%S).txt"
    echo "$REPORT" > "$REPORT_FILE"
    echo ""
    echo -e "${GREEN}✓ 診斷報告已保存到：${NC}"
    echo "$REPORT_FILE"
    echo ""
    echo "請將此文件發送給開發者以獲取幫助。"
    ;;

  0|*)
    echo ""
    echo "已取消。"
    ;;
esac

echo ""
