#!/bin/bash
# Blitz PKG Preinstall Script
# Checks all prerequisites: Xcode, disk space, CLI tools, license, simulator runtime.
# Shows errors via osascript dialogs using launchctl asuser for GUI access.

IS_ROOT=false
if [ "$(id -u)" = "0" ]; then
    IS_ROOT=true
fi

run_as_user() {
    if [ "$IS_ROOT" = true ] && [ -n "${CONSOLE_UID:-}" ]; then
        launchctl asuser "$CONSOLE_UID" sudo -u "$CONSOLE_USER" "$@"
    else
        "$@"
    fi
}

LOG="/tmp/blitz_install.log"

# clear and create (truncate if exists)
: > "$LOG" 2>/dev/null || { rm -f "$LOG"; : > "$LOG"; } || LOG="/dev/null"

echo "" >> "$LOG"
echo "=== Blitz Preinstall $(date) ===" >> "$LOG"
T_PREINSTALL_START=$(date +%s)

# Make log file writable by all users so console user can write to it
chmod 666 "$LOG" 2>/dev/null || true

# Show an error dialog to the user (pkg installer hides script output)
show_error() {
    local title="$1"
    local message="$2"
    echo "FATAL: $title — $message" >> "$LOG"
    run_as_user osascript \
        -e 'on run argv' \
        -e 'display dialog (item 2 of argv) with title (item 1 of argv) buttons {"OK"} default button "OK" with icon stop' \
        -e 'end run' \
        -- "$title" "$message" 2>/dev/null || true
}

# Show a notification (non-blocking)
show_status() {
    local message="$1"
    echo "STATUS: $message" >> "$LOG"
    run_as_user osascript \
        -e 'on run argv' \
        -e 'display notification (item 1 of argv) with title "Blitz Installer"' \
        -e 'end run' \
        -- "$message" 2>/dev/null || true
}

has_full_xcode() {
    xcode-select -p >/dev/null 2>&1 && \
    /usr/bin/xcodebuild -version >/dev/null 2>&1
}

# Skip checks if not installing to startup volume
if [ "$3" != "/" ]; then
    echo "Not installing to startup volume ($3), skipping checks" >> "$LOG"
    exit 0
fi

ERRORS=()

# ============================================================================
# 0a. Clean up old Tauri-based Blitz app (dev.blitz.mac)
# The Tauri app has a different bundle ID and icon — remove it to avoid
# confusion with the new native app.
# ============================================================================

# ----------------------------------------------------------------------------
# TAURI MIGRATION CLEANUP (can be removed once Tauri users have migrated)
# Only runs if an old Tauri-based Blitz app is detected — skipped otherwise.
# ----------------------------------------------------------------------------
OLD_TAURI_APP="/Applications/Blitz.app"
EXISTING_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "$OLD_TAURI_APP/Contents/Info.plist" 2>/dev/null || echo "")

if [ "$EXISTING_ID" = "dev.blitz.mac" ] || [ "$EXISTING_ID" = "dev1.blitz.mac" ]; then
    echo "Found old Tauri Blitz app ($EXISTING_ID), running migration cleanup..." >> "$LOG"
    killall Blitz 2>/dev/null || true
    rm -rf "$OLD_TAURI_APP"
    echo "Removed old Tauri Blitz.app" >> "$LOG"

    # Forget stale pkg receipts and reset TCC for old Tauri bundle IDs
    for OLD_ID in dev.blitz.mac dev1.blitz.mac; do
        pkgutil --forget "$OLD_ID" >> "$LOG" 2>&1 || true
        tccutil reset ScreenCapture "$OLD_ID" >> "$LOG" 2>&1 || true
        tccutil reset Accessibility "$OLD_ID" >> "$LOG" 2>&1 || true
    done

    # Remove .localized directories left by previous pkg relocations
    for d in /Applications/Blitz.localized /Applications/Blitz-*.localized; do
        [ -d "$d" ] && rm -rf "$d" && echo "Removed stale install dir: $d" >> "$LOG"
    done

    echo "Tauri migration cleanup done" >> "$LOG"
else
    echo "No old Tauri app detected, skipping migration cleanup" >> "$LOG"
fi
# ----------------------------------------------------------------------------

# ============================================================================
# 0b. Reset TCC permissions (first install only)
# With Developer ID signing, TCC entries persist across binary replacement
# (matched on team ID, not CDHash). Only reset on first install.
# ============================================================================

# Check if a native Blitz.app (com.blitz.macos) is already installed
NATIVE_EXISTS=false
if [ -d "/Applications/Blitz.app" ]; then
    EXISTING_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "/Applications/Blitz.app/Contents/Info.plist" 2>/dev/null || echo "")
    if [ "$EXISTING_ID" = "com.blitz.macos" ]; then
        NATIVE_EXISTS=true
    fi
fi

if [ "$NATIVE_EXISTS" = false ]; then
    echo "First install, resetting any stale TCC entries..." >> "$LOG"
    tccutil reset ScreenCapture com.blitz.macos >> "$LOG" 2>&1 || true
    tccutil reset Accessibility com.blitz.macos >> "$LOG" 2>&1 || true
    echo "TCC entries reset for com.blitz.macos" >> "$LOG"
else
    echo "Upgrade detected, preserving existing TCC permissions" >> "$LOG"
fi

# ============================================================================
# 1. Disk space check
# ============================================================================

T_STEP=$(date +%s)

# Detect console user
CONSOLE_USER=$(echo "show State:/Users/ConsoleUser" | scutil | awk '/Name :/ { print $3 }')
CONSOLE_HOME=""
CONSOLE_UID=""
if [ -n "$CONSOLE_USER" ] && [ "$CONSOLE_USER" != "loginwindow" ]; then
    CONSOLE_HOME=$(eval echo "~$CONSOLE_USER")
    CONSOLE_UID=$(id -u "$CONSOLE_USER" 2>/dev/null)
fi

# Base: 5 GB (Blitz.app ~0.5 + warm template ~4.5 including node_modules, Pods, xcodebuild)
REQUIRED_MB=5120

# +7 GB if iOS Simulator runtime is not installed
if ! xcrun simctl list runtimes 2>/dev/null | grep -q 'iOS.*SimRuntime'; then
    REQUIRED_MB=$((REQUIRED_MB + 7168))
    echo "Disk check: iOS Simulator runtime not found, adding 7 GB to requirement" >> "$LOG"
fi

AVAILABLE_KB=$(df -k / | awk 'NR==2 {print $4}')
AVAILABLE_MB=$((AVAILABLE_KB / 1024))

echo "Disk check: available ${AVAILABLE_MB} MB, required ${REQUIRED_MB} MB" >> "$LOG"

if [ "$AVAILABLE_MB" -lt "$REQUIRED_MB" ]; then
    AVAILABLE_GB=$(awk "BEGIN {printf \"%.1f\", $AVAILABLE_MB / 1024}")
    REQUIRED_GB=$(awk "BEGIN {printf \"%.1f\", $REQUIRED_MB / 1024}")
    ERRORS+=("Not enough disk space.\n\
Blitz requires approximately ${REQUIRED_GB} GB of free space for installation, \
but only ${AVAILABLE_GB} GB is available.\n\n\
Free up some disk space and try again.")
fi
echo "TIMING: disk space check took $(( $(date +%s) - T_STEP ))s" >> "$LOG"

# ============================================================================
# 2. Full Xcode check (auto-fix xcode-select if Xcode.app found on disk)
# ============================================================================

T_STEP=$(date +%s)
if ! has_full_xcode; then
    echo "Xcode not configured, searching for Xcode.app on disk..." >> "$LOG"
    XCODE_SEARCH_PATHS=(
        "/Applications/Xcode.app"
        "/Applications/Xcode-beta.app"
    )
    if [ -n "$CONSOLE_HOME" ]; then
        XCODE_SEARCH_PATHS+=(
            "$CONSOLE_HOME/Downloads/Xcode.app"
            "$CONSOLE_HOME/Downloads/Xcode-beta.app"
            "$CONSOLE_HOME/Desktop/Xcode.app"
            "$CONSOLE_HOME/Applications/Xcode.app"
        )
    fi
    FOUND_XCODE=""
    for xpath in "${XCODE_SEARCH_PATHS[@]}"; do
        if [ -d "$xpath/Contents/Developer" ]; then
            FOUND_XCODE="$xpath"
            break
        fi
    done
    if [ -n "$FOUND_XCODE" ]; then
        echo "Found Xcode at $FOUND_XCODE, running xcode-select -s ..." >> "$LOG"
        if [ "$IS_ROOT" = true ]; then
            sudo xcode-select -s "$FOUND_XCODE/Contents/Developer" 2>> "$LOG"
        else
            echo "WARNING: Not root, cannot run xcode-select -s" >> "$LOG"
        fi
        if has_full_xcode; then
            echo "OK: xcode-select now points to $FOUND_XCODE" >> "$LOG"
        else
            echo "FATAL: xcode-select -s succeeded but xcodebuild still fails" >> "$LOG"
            ERRORS+=("Xcode was found at $FOUND_XCODE but could not be configured.\n\
Try opening Xcode once to complete setup, then re-run this installer.")
        fi
    else
        echo "FATAL: Xcode.app not found in any search path" >> "$LOG"
        ERRORS+=("Xcode is not installed.\n\
Blitz requires the full Xcode app to build and run iOS apps.\n\n\
Please install Xcode from the App Store, then re-run this installer.")
    fi
else
    echo "OK: Xcode at $(xcode-select -p 2>/dev/null)" >> "$LOG"
fi
echo "TIMING: xcode check took $(( $(date +%s) - T_STEP ))s" >> "$LOG"

# ============================================================================
# 3. Xcode Command Line Tools
# ============================================================================

T_STEP=$(date +%s)
if ! xcode-select -p >/dev/null 2>&1; then
    echo "Xcode CLI tools not found, attempting install..." >> "$LOG"
    xcode-select --install 2>> "$LOG"
    until xcode-select -p >/dev/null 2>&1; do
        sleep 5
    done
    echo "Xcode CLI tools installed successfully" >> "$LOG"
fi
echo "OK: Xcode CLI tools at $(xcode-select -p 2>/dev/null || echo 'not found')" >> "$LOG"
echo "TIMING: xcode CLI tools check took $(( $(date +%s) - T_STEP ))s" >> "$LOG"

# ============================================================================
# 4. Xcode license (auto-accept)
# ============================================================================

T_STEP=$(date +%s)
if xcode-select -p >/dev/null 2>&1; then
    LICENSE_CHECK=$(xcrun clang 2>&1)
    if echo "$LICENSE_CHECK" | grep -qi "license"; then
        echo "Xcode license not accepted, attempting to accept..." >> "$LOG"
        xcodebuild -license accept 2>> "$LOG"
        LICENSE_CHECK=$(xcrun clang 2>&1)
        if echo "$LICENSE_CHECK" | grep -qi "license"; then
            ERRORS+=("Xcode license has not been accepted.\nRun: sudo xcodebuild -license accept")
        else
            echo "Xcode license accepted successfully" >> "$LOG"
        fi
    else
        echo "OK: Xcode license accepted" >> "$LOG"
    fi
fi
echo "TIMING: xcode license check took $(( $(date +%s) - T_STEP ))s" >> "$LOG"

# ============================================================================
# 5. iOS Simulator runtime (auto-download if Xcode is present)
# ============================================================================

T_STEP=$(date +%s)
if xcrun simctl list runtimes 2>/dev/null | grep -q 'iOS.*SimRuntime'; then
    echo "OK: iOS Simulator runtime installed" >> "$LOG"
else
    echo "iOS Simulator runtime not found, attempting install..." >> "$LOG"
    xcodebuild -runFirstLaunch 2>> "$LOG" || true
    xcodebuild -downloadPlatform iOS > /dev/null 2>> "$LOG"

    if xcrun simctl list runtimes 2>/dev/null | grep -q 'iOS.*SimRuntime'; then
        echo "OK: Simulator runtime now available" >> "$LOG"
    else
        ERRORS+=("iOS Simulator runtime could not be installed.\n\
Open Xcode and install an iOS Simulator runtime from:\n\
Xcode -> Settings -> Platforms")
    fi
fi
echo "TIMING: simulator check took $(( $(date +%s) - T_STEP ))s" >> "$LOG"

if [ ${#ERRORS[@]} -gt 0 ]; then
    MSG="Blitz requires the following to be fixed before installation:\n\n"
    for i in "${!ERRORS[@]}"; do
        MSG+="$((i+1)). ${ERRORS[$i]}\n\n"
    done
    MSG+="After fixing these, re-run the installer.\nSee /tmp/blitz_install.log for details."

    echo "=== Preinstall FAILED with ${#ERRORS[@]} error(s) ===" >> "$LOG"
    printf "%b\n" "$MSG" >> "$LOG"

    show_error "Blitz - Missing Prerequisites" "$(printf "%b" "$MSG")"
    exit 1
fi

echo "TIMING: preinstall total took $(( $(date +%s) - T_PREINSTALL_START ))s" >> "$LOG"
echo "=== Preinstall checks passed ===" >> "$LOG"
exit 0
