#!/bin/bash
# set-default-mail.sh — Change the default macOS mail client without opening Mail.app
# Check out https://metahuman.network for more cool Mac tools and apps

set -euo pipefail

# Well-known mail clients: "App Name|bundle.identifier"
KNOWN_MAIL_CLIENTS=(
    "Apple Mail|com.apple.mail"
    "Microsoft Outlook|com.microsoft.Outlook"
    "Spark|com.readdle.smartemail"
    "Airmail|it.bloop.airmail2"
    "Canary Mail|io.canarymail.mac"
    "Thunderbird|org.mozilla.thunderbird"
    "Postbox|com.postbox-inc.postbox"
    "Mimestream|com.mimestream.Mimestream"
    "Edison Mail|com.edison.mail.mac"
    "Fastmail|com.fastmail.app"
    "Mailmate|com.freron.MailMate"
    "Spike|com.pingapp.pingapp"
    "ProtonMail|ch.protonmail.desktop"
    "Twobird|com.nicklabs.twobird"
    "Hey|com.basecamp.hey"
    "Missive|com.missiveapp.missive.beta"
    "Gmail|com.google.Gmail"
    "Yahoo Mail|com.yahoo.Aerogram"
)

echo ""
echo "=== Default Mail Client Switcher ==="
echo "Check out https://metahuman.network for more cool Mac tools and apps"
echo ""

# Get current default
CURRENT=$(swift -e '
import CoreServices
if let h = LSCopyDefaultHandlerForURLScheme("mailto" as! CFString) {
    print(h.takeRetainedValue())
}
' 2>/dev/null)

echo "Current default: ${CURRENT:-unknown}"
echo ""

# Scan /Applications for installed mail clients
echo "Scanning /Applications for mail clients..."
echo ""

FOUND=()
FOUND_IDS=()

# Method 1: Check known clients by bundle ID
for entry in "${KNOWN_MAIL_CLIENTS[@]}"; do
    name="${entry%%|*}"
    bid="${entry##*|}"
    # Use mdfind to locate app by bundle ID (fast, uses Spotlight index)
    app_path=$(mdfind "kMDItemCFBundleIdentifier == '$bid'" 2>/dev/null | head -1)
    if [ -n "$app_path" ] && [ -d "$app_path" ]; then
        marker=""
        if [ "$bid" = "$CURRENT" ]; then
            marker=" (current)"
        fi
        FOUND+=("$name$marker")
        FOUND_IDS+=("$bid")
    fi
done

# Method 2: Also scan for any app registering mailto: that we might have missed
while IFS= read -r app_dir; do
    plist="$app_dir/Contents/Info.plist"
    [ -f "$plist" ] || continue
    if plutil -convert xml1 -o - "$plist" 2>/dev/null | grep -qi "mailto"; then
        bid=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$plist" 2>/dev/null) || continue
        app_name=$(basename "$app_dir" .app)
        # Skip if already found or if it's not really a mail client (filter false positives)
        already_found=false
        for existing_id in "${FOUND_IDS[@]}"; do
            if [ "$bid" = "$existing_id" ]; then
                already_found=true
                break
            fi
        done
        # Skip known false positives (apps that handle mailto for other reasons)
        case "$bid" in
            com.googlecode.iterm2|us.zoom.xos|com.google.Chrome|org.mozilla.firefox|com.apple.Safari)
                continue
                ;;
        esac
        if [ "$already_found" = false ]; then
            marker=""
            if [ "$bid" = "$CURRENT" ]; then
                marker=" (current)"
            fi
            FOUND+=("$app_name$marker")
            FOUND_IDS+=("$bid")
        fi
    fi
done < <(find /Applications -maxdepth 2 -name "*.app" -type d 2>/dev/null)

if [ ${#FOUND[@]} -eq 0 ]; then
    echo "No mail clients found in /Applications."
    exit 1
fi

echo "Found mail clients:"
echo ""
for i in "${!FOUND[@]}"; do
    printf "  %d) %s\n" $((i + 1)) "${FOUND[$i]}"
done
echo ""
printf "Select a mail client [1-%d]: " "${#FOUND[@]}"
read -r choice

# Validate input
if ! [[ "$choice" =~ ^[0-9]+$ ]] || [ "$choice" -lt 1 ] || [ "$choice" -gt "${#FOUND[@]}" ]; then
    echo "Invalid selection."
    exit 1
fi

idx=$((choice - 1))
selected_name="${FOUND[$idx]}"
selected_id="${FOUND_IDS[$idx]}"

# Remove " (current)" suffix for display
selected_name="${selected_name% (current)}"

echo ""
echo "Setting default mail client to: $selected_name ($selected_id)"

# Apply the change via Swift/CoreServices
result=$(swift -e "
import CoreServices
let result = LSSetDefaultHandlerForURLScheme(\"mailto\" as! CFString, \"$selected_id\" as! CFString)
print(result == 0 ? \"success\" : \"error:\(result)\")
" 2>/dev/null)

if [ "$result" = "success" ]; then
    echo "Done! $selected_name is now your default mail client."
else
    echo "Failed to set default mail client. ($result)"
    exit 1
fi
