#!/bin/bash

# Phase 1 Testing Script - Interactive Test Runner
# Guides through all Phase 1 tests with clear prompts for UI interaction

set -e  # Exit on error

# Source shared library
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/alarm-test-lib.sh"

# Phase 1 specific configuration
VERIFY_FIRE=${VERIFY_FIRE:-false}  # Set VERIFY_FIRE=true to enable alarm fire verification
APP_DIR="${SCRIPT_DIR}"
PROJECT_ROOT="$(cd "${APP_DIR}/../.." && pwd)"

# Allow selecting specific tests on the command line (e.g. ./test-phase1.sh 1 2)
SELECTED_TESTS=()

check_plugin_configured() {
    print_info "Checking if plugin is already configured..."
    
    # Wait a moment for app to fully load
    sleep 3
    
    # Check if database exists (indicates plugin has been used)
    DB_EXISTS=$($ADB_BIN shell run-as "${APP_ID}" ls databases/ 2>/dev/null | grep -c "daily_notification" || echo "0")
    
    # Check if SharedPreferences has configuration (more reliable)
    # The plugin stores config in SharedPreferences
    PREFS_EXISTS=$($ADB_BIN shell run-as "${APP_ID}" ls shared_prefs/ 2>/dev/null | grep -c "DailyNotification" || echo "0")
    
    # Check recent logs for configuration activity
    RECENT_CONFIG=$($ADB_BIN logcat -d -t 50 | grep -E "Plugin configured|configurePlugin|Configuration" | tail -3)
    
    if [ "${DB_EXISTS}" -gt "0" ] || [ "${PREFS_EXISTS}" -gt "0" ]; then
        print_success "Plugin appears to be configured (database or preferences exist)"
        
        # Show user what to check in UI
        print_info "Please verify in the app UI that you see:"
        echo "  ⚙️ Plugin Settings: ✅ Configured"
        echo "  🔌 Native Fetcher: ✅ Configured"
        echo ""
        echo "If both show ✅, the plugin is configured and you can skip configuration."
        echo "If either shows ❌ or 'Not configured', you'll need to click 'Configure Plugin'."
        echo ""
        
        return 0
    else
        print_info "Plugin not configured (no database or preferences found)"
        print_info "You will need to click 'Configure Plugin' in the app UI"
        return 1
    fi
}

check_permissions() {
    print_info "Checking notification permissions..."
    
    # Check if POST_NOTIFICATIONS permission is granted (Android 13+)
    PERM_CHECK=$($ADB_BIN shell dumpsys package "${APP_ID}" | grep -A 5 "granted=true" | grep -c "android.permission.POST_NOTIFICATIONS" || echo "0")
    
    # Also check via app's permission status if available
    PERM_GRANTED=false
    if [ "${PERM_CHECK}" -gt "0" ]; then
        PERM_GRANTED=true
    else
        # Check if we're on Android 12 or below (permission not required)
        SDK_VERSION=$($ADB_BIN shell getprop ro.build.version.sdk)
        if [ "${SDK_VERSION}" -lt "33" ]; then
            PERM_GRANTED=true  # Pre-Android 13 doesn't need runtime permission
        fi
    fi
    
    if [ "${PERM_GRANTED}" = true ]; then
        print_success "Notification permissions granted"
        return 0
    else
        print_warn "Notification permissions may not be granted"
        return 1
    fi
}

ensure_permissions() {
    if check_permissions; then
        print_success "Permissions already granted"
        return 0
    else
        print_info "Notification permissions needed"
        wait_for_ui_action "In the app UI, click the 'Request Permissions' button.
        
        This will show a system permission dialog.
        
        Steps:
        1. Click 'Request Permissions' button
        2. In the system dialog, tap 'Allow' to grant notification permission
        3. Return to the app and verify the status shows:
           - 🔔 Notifications: ✅ Granted (or similar)
        
        Once permission is granted, press Enter to continue."
        
        # Re-check permissions
        sleep 2
        if check_permissions; then
            print_success "Permissions granted"
            return 0
        else
            print_warn "Permissions may still not be granted - continuing anyway"
            print_info "If notifications fail, you may need to grant permissions manually"
            return 1
        fi
    fi
}

ensure_plugin_configured() {
    if check_plugin_configured; then
        # Plugin might be configured, but let user verify
        wait_for_ui_action "Please check the Plugin Status section at the top of the app.
        
        If you see:
        - ⚙️ Plugin Settings: ✅ Configured
        - 🔌 Native Fetcher: ✅ Configured
        - 🔔 Notifications: ✅ Granted (or similar)
        
        Then the plugin is already configured - just press Enter to continue.
        
        If any show ❌ or 'Not configured':
        - Click 'Request Permissions' if notifications are not granted
        - Click 'Configure Plugin' if settings/fetcher are not configured
        - Wait for all to show ✅, then press Enter."
        
        # Give a moment for any configuration that just happened
        sleep 2
        print_success "Continuing with tests (plugin configuration verified or skipped)"
        return 0
    else
        # Plugin definitely needs configuration
        print_info "Plugin needs configuration"
        
        # First ensure permissions
        ensure_permissions
        
        wait_for_ui_action "Click the 'Configure Plugin' button in the app UI.
        
        Wait for the status to update:
        - ⚙️ Plugin Settings: Should change to ✅ Configured
        - 🔌 Native Fetcher: Should change to ✅ Configured
        
        Once both show ✅, press Enter to continue."
        
        # Verify configuration completed
        sleep 2
        print_success "Plugin configuration completed (or verified)"
    fi
}

# kill_app is now provided by the library, but Phase 1 uses it with PACKAGE variable
# The library version uses APP_ID, which is set to PACKAGE, so it should work
# But we keep this as a compatibility wrapper if needed

# Phase 1 specific helper: get_current_time (used for fire verification)
get_current_time() {
    $ADB_BIN shell date +%s
}

# Main test execution
main() {
    # Allow selecting specific tests: e.g. `./test-phase1.sh 1 2`
    if [[ "$#" -gt 0 && ( "$1" == "-h" || "$1" == "--help" ) ]]; then
        echo "Usage: $0 [TEST_IDS...]"
        echo ""
        echo "If no TEST_IDS are given, all tests (1, 2, 3, 4) will run."
        echo "Examples:"
        echo "  $0          # run all tests"
        echo "  $0 1        # run only TEST 1"
        echo "  $0 2 3      # run only TEST 2 and TEST 3"
        echo "  $0 4        # run only TEST 4"
        return 0
    fi
    
    SELECTED_TESTS=("$@")
    
    print_header "Phase 1 Testing Script"
    echo "This script will guide you through Phase 1 tests."
    echo "You'll be prompted when UI interaction is needed."
    echo ""
    wait_for_user
    
    # Pre-flight checks
    print_header "Pre-Flight Checks"
    check_adb_connection
    check_emulator_ready
    
    # Build and install
    build_app
    install_app
    
    # Clear logs
    clear_logs
    
    # ============================================
    # TEST 0: Daily Rollover (Core Contract Verification)
    # ============================================
    # Note: This test verifies the core "one notification per day" contract
    # by checking that after a notification fires, the next day's schedule
    # is correctly computed and scheduled. This is a manual/semi-automated test
    # as it requires either waiting for the alarm to fire or manipulating time.
    #
    # To run: Use test ID "0" or enable manually
    # ============================================
    if should_run_test "0" SELECTED_TESTS; then
    print_header "TEST 0: Daily Rollover Verification"
    echo "Purpose: Verify that after a notification fires, the next day's"
    echo "         schedule is correctly computed and only ONE alarm exists."
    echo ""
    echo "Note: This test verifies the core 'one notification per day' contract."
    echo "      It requires either:"
    echo "      1. Scheduling a notification for 'now + N seconds' and waiting, OR"
    echo "      2. Manipulating the emulator clock to cross the fire boundary."
    echo ""
    echo "      For now, this is a MANUAL test - you'll need to verify the"
    echo "      behavior by checking logs and AlarmManager after a notification fires."
    echo ""
    wait_for_user
    
    print_step "1" "Schedule a test notification for near-future (or use existing)..."
    launch_app
    ensure_plugin_configured
    
    # Capture pre-schedule UI state
    take_screenshot "phase1_test0_daily_rollover" "before_scheduling"
    
    INITIAL_COUNT=$(get_plugin_alarm_count)
    SYSTEM_COUNT=$(get_system_alarm_count)
    print_info "Current notification alarms: ${INITIAL_COUNT} (expected before scheduling: 0)"
    print_info "System/other alarms: ${SYSTEM_COUNT} (for context)"
    print_info "Note: Prefetch uses WorkManager (not AlarmManager), so it won't appear in alarm count"
    
    if [ "${INITIAL_COUNT}" -eq "0" ] 2>/dev/null; then
        print_success "✅ No existing notification alarms (clean state)"
        wait_for_ui_action "In the app UI, schedule a daily notification.
        
        For this test, you may want to schedule it for a time very soon
        (e.g., 1-2 minutes from now) to observe the rollover behavior.
        
        This will schedule:
        - 1 notification alarm (AlarmManager) for the specified time
        - 1 prefetch job (WorkManager) for 2 minutes before that time"
        sleep 3  # Give alarm time to be registered in AlarmManager
        
        # Capture post-schedule UI state
        take_screenshot "phase1_test0_daily_rollover" "after_scheduling"
        
        POST_SCHEDULE_COUNT=$(get_plugin_alarm_count)
        
        # Check alarm count after scheduling
        # Note: This is a PRELIMINARY sanity check only - final verdict comes after rollover
        # 0 alarms is likely a race condition (alarm may not be visible yet in dumpsys)
        # Only treat >1 alarms as a real failure (duplicates)
        if [ "${POST_SCHEDULE_COUNT}" -eq "0" ] 2>/dev/null; then
            print_warn "⚠️  Found 0 plugin alarms right after scheduling."
            print_info "ℹ️  Pre-schedule check not reliable; will rely on rollover assertions."
            print_info "ℹ️  The alarm may not be visible in dumpsys yet. Continuing to verify after rollover."
        elif [ "${POST_SCHEDULE_COUNT}" -eq "1" ] 2>/dev/null; then
            print_success "✅ Found 1 notification alarm (expected: 1) – preliminary check passed."
            print_info "ℹ️  This is preliminary check only; final verdict after rollover."
        else
            # count > 1 - this is a real duplicate bug
            print_warn "⚠️  ⚠️  Found ${POST_SCHEDULE_COUNT} notification alarms (expected: 1) – DUPLICATES DETECTED right after scheduling!"
            print_warn "This indicates duplicate NOTIFICATION alarms were created (BUG DETECTED)"
            print_info "Showing alarm blocks for debugging:"
            show_plugin_alarms_compact
            print_info "For more details, run:"
            print_info "  adb shell dumpsys alarm | grep -A 5 'com.timesafari.dailynotification' | sed -n '1,80p'"
        fi
        INITIAL_COUNT="${POST_SCHEDULE_COUNT}"
    fi
    
    # Only show alarm details if we found exactly 1 alarm (skip if 0 due to race condition)
    if [ "${INITIAL_COUNT}" -eq "1" ] 2>/dev/null; then
        print_success "✅ Single notification alarm scheduled (one per day)"
        print_info "Note: Prefetch uses WorkManager (not AlarmManager), so it won't appear in alarm count"
        
        # Show alarm details
        ALARM_DETAILS=$($ADB_BIN shell dumpsys alarm | grep -A 3 "com.timesafari.dailynotification" | grep -A 3 "com.timesafari.daily.NOTIFICATION" | head -10)
        if [ -n "${ALARM_DETAILS}" ]; then
            print_info "Notification alarm details:"
            echo "${ALARM_DETAILS}" | head -5
            echo ""
            
            # Extract trigger time
            ALARM_TRIGGER_MS=$(echo "${ALARM_DETAILS}" | grep -oE "origWhen [0-9]+" | head -1 | awk '{print $2}')
            if [ -n "${ALARM_TRIGGER_MS}" ]; then
                ALARM_TRIGGER_SEC=$((ALARM_TRIGGER_MS / 1000))
                ALARM_READABLE=$(date -d "@${ALARM_TRIGGER_SEC}" 2>/dev/null || echo "${ALARM_TRIGGER_MS} ms")
                print_info "Notification alarm scheduled for: ${ALARM_READABLE}"
                
                # Calculate prefetch time (2 minutes before)
                PREFETCH_SEC=$((ALARM_TRIGGER_SEC - 120))
                PREFETCH_READABLE=$(date -d "@${PREFETCH_SEC}" 2>/dev/null || echo "${PREFETCH_SEC}")
                print_info "Prefetch should be scheduled for: ${PREFETCH_READABLE} (2 minutes before, via WorkManager)"
                
                # Calculate next day
                NEXT_DAY_SEC=$((ALARM_TRIGGER_SEC + 86400))
                NEXT_DAY_READABLE=$(date -d "@${NEXT_DAY_SEC}" 2>/dev/null || echo "${NEXT_DAY_SEC}")
                print_info "Expected next day notification: ${NEXT_DAY_READABLE} (24 hours later)"
            fi
        fi
    elif [ "${INITIAL_COUNT}" -gt "1" ] 2>/dev/null; then
        print_warn "⚠️  Found ${INITIAL_COUNT} notification alarms (expected: 1) - DUPLICATES DETECTED!"
        print_warn "This indicates the duplicate alarm bug - multiple alarms for the same notification"
    fi
    # Note: We intentionally don't print anything for INITIAL_COUNT == 0 here
    # because we already handled it above with the race condition message
    
    print_step "2" "Manual verification steps..."
    echo ""
    echo "To complete this test, you need to:"
    echo "  1. Wait for the notification to fire (or advance emulator clock)"
    echo "  2. Check that the plugin:"
    echo "     - Computed the next day's time (24 hours later)"
    echo "     - Scheduled exactly ONE notification alarm (AlarmManager) for tomorrow"
    echo "     - Scheduled exactly ONE prefetch job (WorkManager) for 2 minutes before tomorrow's notification"
    echo "     - Did NOT create duplicate notification alarms"
    echo "  3. Verify in logs:"
    echo "     - Next run time calculation shows tomorrow's time"
    echo "     - Only one notification alarm scheduled in AlarmManager"
    echo "     - Prefetch job scheduled in WorkManager"
    echo ""
    echo "Expected log patterns:"
    echo "  DNP-SCHEDULE: Scheduling next daily alarm: ... source=ROLLOVER_ON_FIRE"
    echo "  DNP-NOTIFY: Scheduling alarm: triggerTime=<tomorrow's time>"
    echo "  DNP-SCHEDULE: Scheduling OS alarm: variant=ALARM_CLOCK, action=com.timesafari.daily.NOTIFICATION, ..."
    echo ""
    echo "When scheduling the test notification, expect:"
    echo "  DNP-SCHEDULE: ... source=TEST_NOTIFICATION"
    echo ""
    echo "Alarm shape in dumpsys:"
    echo "  RTC_WAKEUP, ALARM_CLOCK, tag=*walarm*:com.timesafari.daily.NOTIFICATION"
    echo ""
    echo "After notification fires, run:"
    echo "  adb shell dumpsys alarm | grep -A 3 'com.timesafari.dailynotification'"
    echo "  adb logcat -d | grep -E 'DNP-SCHEDULE|DNP-NOTIFY' | tail -20"
    echo ""
    
    wait_for_ui_action "After the notification fires (or you advance the clock),
    check the logs and AlarmManager to verify:
    
    1. Only ONE alarm exists (one per day)
    2. The alarm time is for tomorrow (24 hours later)
    3. No duplicate alarms were created
    
    Press Enter when you've verified this (or to skip this test)."
    
    print_info "Polling for stable alarm count (allowing up to ~10 seconds for Android to settle)..."
    POST_ROLLOVER_COUNT=$(wait_for_stable_plugin_alarm_count 5 2)
    SYSTEM_FINAL=$(get_system_alarm_count)
    print_info "Notification alarms after rollover: ${POST_ROLLOVER_COUNT} (expected: 1)"
    print_info "System/other alarms: ${SYSTEM_FINAL} (for context)"
    print_info "Note: Prefetch is scheduled via WorkManager (not AlarmManager), so it won't appear in alarm count"
    
    # Capture post-rollover UI state
    take_screenshot "phase1_test0_daily_rollover" "after_rollover_check"
    
    # After rollover, the state should be stable - this is the real assertion point
    if [ "${POST_ROLLOVER_COUNT}" -eq "1" ] 2>/dev/null; then
        print_success "✅ TEST 0 PASSED: Daily rollover created exactly one NOTIFICATION alarm for tomorrow."
        print_info "Expected state after rollover:"
        echo "  ✅ 1 notification alarm (AlarmManager) for tomorrow"
        echo "  ✅ 1 prefetch job (WorkManager) for 2 minutes before tomorrow's notification"
    elif [ "${POST_ROLLOVER_COUNT}" -gt "1" ] 2>/dev/null; then
        print_warn "⚠️  ⚠️  TEST 0 FAILED: Daily rollover created ${POST_ROLLOVER_COUNT} NOTIFICATION alarms (duplicates)."
        print_warn "This indicates duplicate NOTIFICATION alarms were created (BUG DETECTED)"
        take_failure_screenshot "phase1_test0_daily_rollover" "duplicate_alarms"
        echo ""
        print_info "Showing alarm blocks for debugging:"
        show_plugin_alarms_compact
        echo ""
        print_info "Check scheduling logs for multiple DNP-SCHEDULE entries:"
        print_info "  adb logcat -d | grep 'DNP-SCHEDULE\|DNP-NOTIFY' | tail -20"
        echo ""
        print_info "Possible causes:"
        echo "  - Multiple scheduling paths racing (rollover + recovery)"
        echo "  - Old alarm wasn't canceled before scheduling new one"
        echo "  - Different scheduleIds used for same trigger time"
        echo "  - Idempotence check not working correctly"
    else
        # count is 0 or invalid - rollover may have failed
        print_warn "⚠️  TEST 0 INCONCLUSIVE: No NOTIFICATION alarm found after rollover (expected 1, got 0)"
        print_warn "This indicates the rollover did not schedule tomorrow's alarm correctly"
        take_failure_screenshot "phase1_test0_daily_rollover" "no_alarm_after_rollover"
        echo ""
        print_info "Showing alarm blocks for debugging:"
        show_plugin_alarms_compact
        echo ""
        print_info "Expected log pattern after fire:"
        echo "  DNP-SCHEDULE: Scheduling next daily alarm: ... source=ROLLOVER_ON_FIRE"
        echo "  DNP-NOTIFY: Scheduling alarm: triggerTime=<tomorrow>"
        echo "  DNP-SCHEDULE: Scheduling OS alarm: variant=ALARM_CLOCK, action=com.timesafari.daily.NOTIFICATION, ..."
        echo ""
        print_info "Check logs for rollover scheduling errors:"
        print_info "  adb logcat -d | grep 'DNP-SCHEDULE\|DNP-NOTIFY' | tail -20"
        echo ""
        print_info "Manual verification:"
        echo "  If dumpsys shows a single RTC_WAKEUP alarm with"
        echo "  tag=*walarm*:com.timesafari.daily.NOTIFICATION for tomorrow,"
        echo "  treat TEST 0 as manually PASSED and update the script expectations later."
    fi
    
    wait_for_user
    fi
    
    # ============================================
    # TEST 1: Force-Stop Recovery - Database Restoration
    # ============================================
    if should_run_test "1" SELECTED_TESTS; then
    print_header "TEST 1: Force-Stop Recovery - Database Restoration"
    echo "Purpose: Verify that after force-stop (which clears alarms), recovery"
    echo "        uses the database to rebuild alarms on app relaunch."
    echo ""
    echo "Note: App supports one alarm per day."
    echo ""
    echo "Test sequence:"
    echo "  1. Clean start - verify no lingering alarms"
    echo "  2. Schedule one alarm → Verify it exists in AlarmManager"
    echo "  3. Force-stop app → Verify alarm is cleared (count = 0)"
    echo "  4. Relaunch app → Verify recovery rebuilds alarm from database"
    echo "  5. Verify alarm actually fires at scheduled time (optional)"
    echo ""
    wait_for_user
    
    # ============================================
    # Step 1: Clean start - verify no lingering alarms
    # ============================================
    print_step "1" "Clean start - checking for lingering alarms..."
    LINGERING_COUNT=$(get_plugin_alarm_count)
    SYSTEM_COUNT=$(get_system_alarm_count)
    print_info "Current plugin notification alarms: ${LINGERING_COUNT}"
    print_info "System/other alarms: ${SYSTEM_COUNT} (for context)"
    
    if [ "${LINGERING_COUNT}" -gt "0" ] 2>/dev/null; then
        print_warn "Found ${LINGERING_COUNT} lingering plugin alarm(s) - these will interfere with TEST 1."
        print_info "TEST 1 needs a clean state (no existing plugin alarms)."
        print_info "Resetting app state via uninstall + reinstall..."
        
        # Uninstall existing app
        print_info "Uninstalling existing app..."
        set +e
        uninstall_output="$($ADB_BIN uninstall "$APP_ID" 2>&1)"
        uninstall_status=$?
        set -e
        
        if [ $uninstall_status -eq 0 ]; then
            print_success "App uninstall succeeded (clean slate)."
        else
            if grep -q "DELETE_FAILED_INTERNAL_ERROR" <<<"$uninstall_output"; then
                print_info "No existing app to uninstall (continuing)"
            else
                print_warn "App uninstall reported an error: $uninstall_output (continuing anyway)"
            fi
        fi
        
        # Reinstall APK
        print_info "Reinstalling APK..."
        if $ADB_BIN install -r "$APK_PATH" >/dev/null 2>&1; then
            print_success "App reinstall succeeded."
        else
            print_error "App reinstall FAILED - cannot proceed with TEST 1."
            print_warn "Marking TEST 1 as INCONCLUSIVE due to dirty starting state."
            take_failure_screenshot "phase1_test1_force_stop" "dirty_state_reinstall_failed"
            wait_for_user
            # Skip to end of TEST 1 block
            goto_test1_end=true
        fi
        
        if [ "${goto_test1_end:-false}" != "true" ]; then
            # Verify install
            if ! $ADB_BIN shell pm list packages | grep -q "$APP_ID"; then
                print_error "App not found in package list after reinstall - aborting TEST 1."
                take_failure_screenshot "phase1_test1_force_stop" "dirty_state_verify_failed"
                wait_for_user
                goto_test1_end=true
            fi
        fi
        
        if [ "${goto_test1_end:-false}" != "true" ]; then
            # Clear logs
            print_info "Clearing logcat buffer after reinstall..."
            $ADB_BIN logcat -c || true
            
            # Re-check plugin alarms
            print_info "Rechecking plugin alarms after reset..."
            sleep 2  # Give system time to clear alarms
            LINGERING_COUNT=$(get_plugin_alarm_count)
            print_info "Plugin alarms after reset: ${LINGERING_COUNT} (expected: 0)"
            
            if [ "${LINGERING_COUNT}" -ne "0" ] 2>/dev/null; then
                print_warn "TEST 1 starting with non-zero alarm count even after reset; treating as INCONCLUSIVE."
                print_info "This may indicate device-specific behavior where alarms persist across uninstall."
                take_failure_screenshot "phase1_test1_force_stop" "unexpected_alarms_after_reset"
                wait_for_user
                goto_test1_end=true
            fi
        fi
        
        if [ "${goto_test1_end:-false}" = "true" ]; then
            print_warn "TEST 1 skipped due to inability to achieve clean starting state."
            wait_for_user
        else
            print_success "App state reset complete. TEST 1 starting from clean state."
        fi
    else
        print_success "No lingering plugin alarms found (clean state)"
    fi
    
    # Skip remaining TEST 1 steps if we couldn't achieve clean state
    if [ "${goto_test1_end:-false}" != "true" ]; then
    
    # ============================================
    # Step 2: Schedule a known future alarm
    # ============================================
    print_step "2" "Launch app and schedule alarm..."
    launch_app
    ensure_plugin_configured
    
    wait_for_ui_action "In the app UI, click the 'Test Notification' button.
    
    This will schedule ONE notification for 4 minutes in the future.
    (App supports one alarm per day)
    
    The alarm will be stored in the database AND scheduled in AlarmManager."
    
    print_step "3" "Verifying alarm exists in AlarmManager (BEFORE force-stop)..."
    sleep 2
    
    ALARM_COUNT_BEFORE=$(get_plugin_alarm_count)
    SYSTEM_COUNT_BEFORE=$(get_system_alarm_count)
    print_info "Plugin alarms: ${ALARM_COUNT_BEFORE} (expected: 1)"
    print_info "System/other alarms: ${SYSTEM_COUNT_BEFORE} (for context)"
    
    if [ "${ALARM_COUNT_BEFORE}" -eq "0" ] 2>/dev/null; then
        print_error "No plugin alarms found in AlarmManager - cannot test force-stop recovery"
        print_info "Make sure you clicked 'Test Notification' and wait a moment"
        wait_for_user
        # Re-check
        ALARM_COUNT_BEFORE=$(get_plugin_alarm_count)
        if [ "${ALARM_COUNT_BEFORE}" -eq "0" ] 2>/dev/null; then
            print_error "Still no alarms found - aborting test"
            exit 1
        fi
    fi
    
    if [ "${ALARM_COUNT_BEFORE}" -eq "1" ] 2>/dev/null; then
        print_success "✅ Single plugin alarm confirmed in AlarmManager (one per day)"
    else
        print_warn "⚠️  Found ${ALARM_COUNT_BEFORE} plugin alarms (expected: 1) - continuing anyway"
    fi
    
    # Capture alarm details for later verification
    ALARM_DETAILS_BEFORE=$($ADB_BIN shell dumpsys alarm | grep -A 3 "$APP_ID" | head -10)
    print_info "Alarm details:"
    echo "${ALARM_DETAILS_BEFORE}" | head -5
    echo ""
    
    # Extract trigger time for later verification
    ALARM_TRIGGER_MS=$(echo "${ALARM_DETAILS_BEFORE}" | grep -oE "origWhen [0-9]+" | head -1 | awk '{print $2}')
    if [ -n "${ALARM_TRIGGER_MS}" ]; then
        ALARM_TRIGGER_SEC=$((ALARM_TRIGGER_MS / 1000))
        ALARM_READABLE=$(date -d "@${ALARM_TRIGGER_SEC}" 2>/dev/null || echo "${ALARM_TRIGGER_SEC}")
        print_info "Alarm scheduled for: ${ALARM_READABLE} (${ALARM_TRIGGER_MS} ms)"
    fi
    
    print_info "Checking logs for scheduling confirmation..."
    $ADB_BIN logcat -d | grep -E "DN|SCHEDULE|Stored notification content" | tail -5
    echo ""
    
    wait_for_user
    
    # ============================================
    # Step 3: Force-stop the app (clears alarms)
    # ============================================
    print_step "4" "Force-stopping app (clears all alarms)..."
    print_warn "Force-stop will clear ALL alarms from AlarmManager"
    print_info "Executing: $ADB_BIN shell am force-stop ${APP_ID}"
    force_stop_app
    sleep 2
    
    # Verify app is stopped (force_stop_app already handles this)
    
    # ============================================
    # Step 4: Verify alarms are MISSING (cleared by OS)
    # ============================================
    print_step "5" "Verifying alarms are MISSING from AlarmManager (AFTER force-stop)..."
    sleep 1
    ALARM_COUNT_AFTER=$(get_plugin_alarm_count)
    SYSTEM_COUNT_AFTER=$(get_system_alarm_count)
    print_info "Plugin alarms after force-stop: ${ALARM_COUNT_AFTER} (expected: 0)"
    print_info "System/other alarms: ${SYSTEM_COUNT_AFTER} (for context)"
    
    if [ "${ALARM_COUNT_AFTER}" -eq "0" ] 2>/dev/null; then
        print_success "✅ Plugin alarms cleared by force-stop (count: ${ALARM_COUNT_AFTER})"
        print_info "This confirms: Force-stop cleared alarms from AlarmManager"
    else
        print_warn "⚠️  Plugin alarms still present after force-stop (count: ${ALARM_COUNT_AFTER})"
        print_info "Some devices/OS versions may not clear alarms on force-stop"
        print_info "Continuing test anyway - recovery should still work"
    fi
    
    wait_for_user
    
    # ============================================
    # Step 5: Relaunch app (triggers recovery from database)
    # ============================================
    print_step "6" "Relaunching app (triggers recovery from database)..."
    clear_logs
    launch_app
    sleep 4  # Give recovery time to run
    
    # ============================================
    # Step 6: Verify recovery rebuilt alarms from database
    # ============================================
    print_step "7" "Verifying recovery rebuilt alarms from database..."
    sleep 2
    ALARM_COUNT_RECOVERED=$(get_plugin_alarm_count)
    SYSTEM_COUNT_RECOVERED=$(get_system_alarm_count)
    print_info "Plugin alarms after recovery: ${ALARM_COUNT_RECOVERED} (expected: 1)"
    print_info "System/other alarms: ${SYSTEM_COUNT_RECOVERED} (for context)"
    
    print_info "Checking recovery logs..."
    check_recovery_logs
    
    print_info "Expected log output:"
    echo "  DNP-REACTIVATION: Starting app launch recovery"
    echo "  DNP-REACTIVATION: Rescheduled alarm: <id> for <time>"
    echo "  DNP-REACTIVATION: Cold start recovery complete: ... rescheduled>=1, ..."
    echo ""
    
    # Check recovery logs for rescheduling and recovery source
    RECOVERY_RESULT=$($ADB_BIN logcat -d | grep "Cold start recovery complete\|Boot recovery complete" | tail -1)
    RESCHEDULED_COUNT=$(echo "${RECOVERY_RESULT}" | grep -oE "rescheduled=[0-9]+" | grep -oE "[0-9]+" || echo "0")
    VERIFIED_COUNT=$(echo "${RECOVERY_RESULT}" | grep -oE "verified=[0-9]+" | grep -oE "[0-9]+" || echo "0")
    
    # Check for explicit recovery source indication (if logged)
    RECOVERY_SOURCE=$($ADB_BIN logcat -d | grep -E "recovery source|from database|DATABASE" | tail -1 || echo "")
    
    # Pass/fail criteria
    TEST1_PASSED=false
    
    if [ "${ALARM_COUNT_RECOVERED}" -gt "0" ] 2>/dev/null; then
        print_success "✅ Alarms restored in AlarmManager (count: ${ALARM_COUNT_RECOVERED})"
        if [ "${RESCHEDULED_COUNT}" -gt "0" ] 2>/dev/null; then
            print_success "✅ Recovery logs confirm rescheduling (rescheduled=${RESCHEDULED_COUNT})"
            TEST1_PASSED=true
        else
            print_warn "⚠️  Alarms restored but logs show rescheduled=0"
            print_info "This might be okay if alarms were verified instead of rescheduled"
            # Still pass if alarms are restored, even if rescheduled=0
            TEST1_PASSED=true
        fi
    else
        print_error "❌ No alarms restored (count: ${ALARM_COUNT_RECOVERED})"
        print_info "Recovery may have failed or alarms were not in database"
    fi
    
    if [ "${TEST1_PASSED}" = true ]; then
        print_success "TEST 1 PASSED: Recovery successfully rebuilt alarms from database!"
        print_info "Summary:"
        echo "  - Before force-stop: ${ALARM_COUNT_BEFORE} alarm(s)"
        echo "  - After force-stop: ${ALARM_COUNT_AFTER} alarm(s) (cleared)"
        echo "  - After recovery: ${ALARM_COUNT_RECOVERED} alarm(s) (rebuilt)"
        echo "  - Rescheduled: ${RESCHEDULED_COUNT} alarm(s)"
        echo "  - Verified: ${VERIFIED_COUNT} alarm(s)"
        if [ -n "${RECOVERY_SOURCE}" ]; then
            echo "  - Recovery source: ${RECOVERY_SOURCE}"
        fi
    else
        print_error "TEST 1 FAILED: Recovery did not rebuild alarms correctly"
        print_info "Check logs above for recovery errors"
    fi
    
    # ============================================
    # Step 7: Verify alarms actually fire (optional, controlled by VERIFY_FIRE flag)
    # ============================================
    if [ "${VERIFY_FIRE}" = "true" ] && [ -n "${ALARM_TRIGGER_MS}" ]; then
        print_step "8" "Verifying alarm fires at scheduled time..."
        
        # Get current time in milliseconds
        CURRENT_TIME_SEC=$(get_current_time)
        CURRENT_TIME_MS=$((CURRENT_TIME_SEC * 1000))
        WAIT_MS=$((ALARM_TRIGGER_MS - CURRENT_TIME_MS))
        
        if [ "${WAIT_MS}" -lt 0 ]; then
            print_warn "Alarm time already passed (${WAIT_MS} ms ago); skipping fire verification"
        else
            WAIT_SEC=$((WAIT_MS / 1000))
            
            # Clamp upper bound to prevent accidentally waiting 30+ minutes
            if [ "${WAIT_SEC}" -gt 600 ]; then
                print_warn "Alarm is >10 minutes away (${WAIT_SEC}s); skipping fire verification"
                print_info "To test fire verification, schedule alarm closer to current time"
                print_info "Or set a shorter test alarm interval in the app"
            else
                print_info "Alarm scheduled for: ${ALARM_READABLE}"
                print_info "Current time: $(date -d "@${CURRENT_TIME_SEC}" 2>/dev/null || echo "${CURRENT_TIME_SEC}")"
                print_info "Waiting ~${WAIT_SEC} seconds for alarm to fire..."
                
                # Clear logs before waiting
                clear_logs
                
                # Wait for alarm time (with a small buffer)
                sleep ${WAIT_SEC}
                
                # Give alarm a moment to fire and log
                sleep 2
                
                print_info "Checking logs for fired alarm..."
                ALARM_FIRED=$($ADB_BIN logcat -d | grep -E "DNP-RECEIVE|DNP-NOTIFY|DNP-WORK|Alarm fired|Notification displayed" | tail -10)
                
                if [ -n "${ALARM_FIRED}" ]; then
                    print_success "✅ Alarm fired! Logs:"
                    echo "${ALARM_FIRED}"
                else
                    print_warn "⚠️  No alarm fire logs found"
                    print_info "This might mean:"
                    echo "  - Alarm fired but logs were cleared"
                    echo "  - Alarm receiver didn't log"
                    echo "  - Check notification tray manually"
                    print_info "Recent logs:"
                    $ADB_BIN logcat -d | grep -E "DNP|DailyNotification" | tail -10
                fi
            fi
        fi
    elif [ "${VERIFY_FIRE}" = "true" ]; then
        print_info "Skipping fire verification (alarm trigger time not captured)"
    else
        print_info "Skipping fire verification (VERIFY_FIRE=false, set VERIFY_FIRE=true to enable)"
    fi
    
    fi  # End of "if goto_test1_end != true" block (wraps all TEST 1 steps after clean state check)
    
    wait_for_user
    fi  # End of "if should_run_test 1" block
    
    # ============================================
    # TEST 2: Schedule Update (One-Per-Day Semantics)
    # ============================================
    if should_run_test "2" SELECTED_TESTS; then
    print_header "TEST 2: Schedule Update Verification"
    echo "Purpose: Verify that updating the schedule time maintains 'one per day' semantics."
    echo ""
    echo "Note: This test verifies that when the schedule time changes, the old alarm"
    echo "      is canceled and only the new one remains (one notification per day)."
    echo ""
    wait_for_user
    
    print_step "1" "Launch app and verify initial schedule"
    launch_app
    ensure_plugin_configured
    
    # Get initial alarm count
    INITIAL_ALARM_COUNT=$(get_plugin_alarm_count)
    SYSTEM_ALARM_COUNT=$(get_system_alarm_count)
    print_info "Plugin alarms: ${INITIAL_ALARM_COUNT} (expected: 1)"
    print_info "System/other alarms: ${SYSTEM_ALARM_COUNT} (for context)"
    
    if [ "${INITIAL_ALARM_COUNT}" -eq "1" ] 2>/dev/null; then
        print_success "✅ Initial alarm confirmed (one per day)"
    elif [ "${INITIAL_ALARM_COUNT}" -eq "0" ] 2>/dev/null; then
        print_warn "⚠️  No initial alarm found - scheduling one first..."
        wait_for_ui_action "In the app UI, schedule a daily notification (e.g., click 'Test Notification')."
        sleep 2
        INITIAL_ALARM_COUNT=$(get_plugin_alarm_count)
        if [ "${INITIAL_ALARM_COUNT}" -eq "1" ] 2>/dev/null; then
            print_success "✅ Alarm scheduled"
        else
            print_error "Failed to schedule initial alarm"
            wait_for_user
        fi
    else
        print_warn "⚠️  Found ${INITIAL_ALARM_COUNT} plugin alarms (expected: 1) - continuing anyway"
    fi
    
    print_step "2" "Updating schedule time"
    wait_for_ui_action "In the app UI, change the schedule time (e.g., from 06:50 to 07:10)
    and apply the schedule.
    
    This should cancel the old alarm and schedule a new one at the new time.
    You should still have exactly 1 alarm (one per day)."
    
    sleep 3
    check_alarm_status
    
    UPDATED_ALARM_COUNT=$(get_plugin_alarm_count)
    print_info "Plugin alarms after update: ${UPDATED_ALARM_COUNT} (expected: 1)"
    
    if [ "${UPDATED_ALARM_COUNT}" -eq "1" ] 2>/dev/null; then
        print_success "✅ Single alarm confirmed after schedule update (one per day maintained)"
    elif [ "${UPDATED_ALARM_COUNT}" -gt "1" ] 2>/dev/null; then
        print_error "❌ TEST 2 FAILED: Found ${UPDATED_ALARM_COUNT} plugin alarms after update (expected: 1)"
        print_error "   Old alarm was NOT canceled - violates 'one per day' semantics"
        print_info "   This indicates the plugin did not clean up existing schedules before creating new one"
        TEST2_FAILED=true
    else
        print_warn "⚠️  Found ${UPDATED_ALARM_COUNT} plugin alarms (expected: 1) - no alarm scheduled after update"
    fi
    
    print_step "3" "Killing app and relaunching (triggers recovery)..."
    kill_app
    clear_logs
    launch_app
    
    print_step "4" "Checking recovery logs for verification..."
    sleep 3
    check_recovery_logs
    
    print_info "Expected log output (either):"
    echo "  DNP-REACTIVATION: Verified scheduled alarm: <id> at <time>"
    echo "    OR"
    echo "  DNP-REACTIVATION: Rescheduled missing alarm: <id> at <time>"
    echo "  DNP-REACTIVATION: Cold start recovery complete: ..., verified=1 or rescheduled=1, ..."
    echo ""
    
    RECOVERY_RESULT=$($ADB_BIN logcat -d | grep "Cold start recovery complete" | tail -1)
    
    # Extract counts from recovery result
    RESCHEDULED_COUNT=$(echo "${RECOVERY_RESULT}" | grep -oE "rescheduled=[0-9]+" | grep -oE "[0-9]+" || echo "0")
    VERIFIED_COUNT=$(echo "${RECOVERY_RESULT}" | grep -oE "verified=[0-9]+" | grep -oE "[0-9]+" || echo "0")
    
    # Verify alarm count after recovery
    ALARM_COUNT_AFTER_RECOVERY=$(get_plugin_alarm_count)
    print_info "Plugin alarms after recovery: ${ALARM_COUNT_AFTER_RECOVERY} (expected: 1)"
    
    # CRITICAL: Test fails if alarm count > 1 after recovery (violates "one per day")
    if [ "${ALARM_COUNT_AFTER_RECOVERY}" -gt "1" ] 2>/dev/null; then
        print_error "❌ TEST 2 FAILED: Found ${ALARM_COUNT_AFTER_RECOVERY} plugin alarms after recovery (expected: 1)"
        print_error "   Multiple schedules in database caused recovery to reschedule duplicates"
        print_error "   This violates 'one per day' semantics - only one notification per day should exist"
        TEST2_FAILED=true
    fi
    
    if [ "${RESCHEDULED_COUNT}" -gt "0" ] 2>/dev/null; then
        if [ "${ALARM_COUNT_AFTER_RECOVERY}" -eq "1" ] 2>/dev/null; then
            print_success "✅ TEST 2 PASSED: Missing alarm was detected and rescheduled (rescheduled=${RESCHEDULED_COUNT})!"
            print_success "✅ Single alarm confirmed after recovery (one per day maintained)"
        elif [ "${TEST2_FAILED:-false}" != "true" ]; then
            print_warn "⚠️  Recovery rescheduled ${RESCHEDULED_COUNT} alarm(s), but alarm count is ${ALARM_COUNT_AFTER_RECOVERY} (expected: 1)"
        fi
    elif [ "${VERIFIED_COUNT}" -gt "0" ] 2>/dev/null; then
        if [ "${ALARM_COUNT_AFTER_RECOVERY}" -eq "1" ] 2>/dev/null; then
            print_success "✅ TEST 2 PASSED: Alarm verified in AlarmManager (verified=${VERIFIED_COUNT})!"
            print_success "✅ Single alarm confirmed after recovery (one per day maintained)"
        elif [ "${TEST2_FAILED:-false}" != "true" ]; then
            print_warn "⚠️  Recovery verified ${VERIFIED_COUNT} alarm(s), but alarm count is ${ALARM_COUNT_AFTER_RECOVERY} (expected: 1)"
        fi
    elif [ "${RESCHEDULED_COUNT}" -eq "0" ] 2>/dev/null && [ "${VERIFIED_COUNT}" -eq "0" ] 2>/dev/null; then
        if [ "${ALARM_COUNT_AFTER_RECOVERY}" -eq "1" ] 2>/dev/null; then
            print_success "✅ TEST 2 PASSED: No recovery needed - alarm already properly scheduled"
            print_success "✅ Single alarm confirmed (one per day maintained)"
        else
            print_warn "⚠️  TEST 2: No verification/rescheduling needed (both verified=0 and rescheduled=0)"
            print_info "This might mean:"
            echo "  - Alarm was already properly scheduled and didn't need recovery"
            echo "  - Recovery didn't detect any issues"
            if [ "${ALARM_COUNT_AFTER_RECOVERY}" -eq "1" ] 2>/dev/null; then
                print_success "✅ Single alarm still present - recovery may have verified it silently"
            fi
        fi
    else
        print_error "TEST 2 INCONCLUSIVE: Could not find recovery result"
        print_info "Recovery result: ${RECOVERY_RESULT}"
    fi
    
    # Final verdict
    if [ "${TEST2_FAILED:-false}" = "true" ]; then
        print_error ""
        print_error "════════════════════════════════════════════════════════════"
        print_error "TEST 2 FINAL RESULT: ❌ FAILED"
        print_error "════════════════════════════════════════════════════════════"
        print_error "Reason: Multiple alarms detected - violates 'one per day' semantics"
        print_error "Expected: 1 alarm after update and after recovery"
        print_error "Actual: ${UPDATED_ALARM_COUNT} after update, ${ALARM_COUNT_AFTER_RECOVERY} after recovery"
        print_error "════════════════════════════════════════════════════════════"
    fi
    
    print_step "5" "Verifying alarms are still scheduled in AlarmManager..."
    check_alarm_status
    
    wait_for_user
    fi
    
    # ============================================
    # TEST 3: Recovery Timeout
    # ============================================
    if should_run_test "3" SELECTED_TESTS; then
    print_header "TEST 3: Recovery Timeout"
    echo "Purpose: Verify recovery times out gracefully."
    echo ""
    echo "Note: This test requires creating many schedules (100+)."
    echo "For now, we'll verify the timeout mechanism exists."
    echo ""
    wait_for_user
    
    print_step "1" "Checking recovery timeout implementation..."
    if grep -q "RECOVERY_TIMEOUT_SECONDS.*2L" "${PROJECT_ROOT}/android/src/main/java/com/timesafari/dailynotification/ReactivationManager.kt"; then
        print_success "Timeout is set to 2 seconds"
    else
        print_error "Timeout not found in code"
    fi
    
    if grep -q "withTimeout" "${PROJECT_ROOT}/android/src/main/java/com/timesafari/dailynotification/ReactivationManager.kt"; then
        print_success "Timeout protection is implemented"
    else
        print_error "Timeout protection not found"
    fi
    
    print_info "TEST 3: Timeout mechanism verified in code"
    print_info "Full test (100+ schedules) can be done manually if needed"
    
    wait_for_user
    fi
    
    # ============================================
    # TEST 4: Invalid Data Handling
    # ============================================
    if should_run_test "4" SELECTED_TESTS; then
    print_header "TEST 4: Invalid Data Handling"
    echo "Purpose: Verify invalid data doesn't crash recovery."
    echo ""
    echo "This test injects invalid data (empty IDs, null nextRunAt) and"
    echo "verifies that recovery handles it gracefully without crashing."
    echo ""
    wait_for_user
    
    print_step "1" "Injecting invalid test data via plugin API..."
    
    # Clear logs before test
    $ADB_BIN logcat -c > /dev/null 2>&1
    
    # Inject invalid data using plugin method
    INJECT_RESULT=$($ADB_BIN shell "am start -a android.intent.action.VIEW -d 'capacitor://localhost/inject-invalid-test-data' ${APP_ID}/.MainActivity" 2>&1)
    
    # Better approach: Use Capacitor bridge via JavaScript
    # We'll use a test HTML page that calls the plugin method
    print_info "Using plugin API to inject invalid data..."
    
    # Create temporary test script
    TEST_SCRIPT=$(mktemp)
    cat > "${TEST_SCRIPT}" << 'EOF'
// Inject invalid test data
(async () => {
    try {
        const result = await window.DailyNotification.injectInvalidTestData({
            injectEmptyScheduleId: true,
            injectNullNextRunAt: true,
            injectEmptyNotificationId: true
        });
        console.log('TEST4: Invalid data injected:', result);
        document.body.innerHTML = '<h1>TEST 4: Invalid Data Injected</h1><pre>' + JSON.stringify(result, null, 2) + '</pre>';
    } catch (error) {
        console.error('TEST4: Failed to inject invalid data:', error);
        document.body.innerHTML = '<h1>TEST 4: Error</h1><pre>' + error.message + '</pre>';
    }
})();
EOF
    
    # Copy test script to device (if we had a way to execute it)
    # For now, we'll use the plugin method directly via ADB shell and JavaScript bridge
    print_info "Injecting invalid data via Capacitor bridge..."
    
    # Alternative: Use adb shell to execute JavaScript in the app
    # This requires the app to be running and have a way to execute JS
    # For now, let's use a simpler approach: check if debuggable and use direct DB access
    # OR use the plugin method if the app is running
    
    # Check if app is debuggable (look for DEBUGGABLE flag)
    IS_DEBUGGABLE=false
    if $ADB_BIN shell dumpsys package "${APP_ID}" | grep -qi "DEBUGGABLE"; then
        IS_DEBUGGABLE=true
    fi
    
    if [ "${IS_DEBUGGABLE}" = "true" ]; then
        print_success "App is debuggable - can inject data via plugin or database"
        
        print_step "2" "Injecting invalid data via direct database access..."
        
        # Launch app first to ensure database is initialized
        print_info "Launching app to initialize database..."
        $ADB_BIN shell am start -n "${APP_ID}/.MainActivity" > /dev/null 2>&1
        sleep 2
        
        # Stop app before database injection (prevents locking issues)
        print_info "Stopping app before database injection..."
        $ADB_BIN shell am force-stop "${APP_ID}"
        sleep 1
        
        # Inject invalid data via direct database access
        print_info "Injecting invalid test data into database..."
        
        # Calculate next run time (24 hours from now in milliseconds)
        NEXT_RUN=$(($(date +%s) * 1000 + 86400000))
        PAST_TIME=$(($(date +%s) * 1000 - 3600000))
        NOW_TIME=$(($(date +%s) * 1000))
        
        # Inject schedule with empty ID
        print_info "  - Injecting schedule with empty ID..."
        $ADB_BIN shell "run-as ${APP_ID} sqlite3 databases/daily_notification_plugin.db \"INSERT OR REPLACE INTO schedules (id, kind, cron, clockTime, enabled, nextRunAt, jitterMs, backoffPolicy) VALUES ('', 'notify', '0 9 * * *', '09:00', 1, ${NEXT_RUN}, 0, 'exp');\"" 2>&1
        
        # Inject schedule with null nextRunAt
        print_info "  - Injecting schedule with null nextRunAt..."
        $ADB_BIN shell "run-as ${APP_ID} sqlite3 databases/daily_notification_plugin.db \"INSERT OR REPLACE INTO schedules (id, kind, cron, clockTime, enabled, nextRunAt, jitterMs, backoffPolicy) VALUES ('test_null_nextrunat', 'notify', '0 9 * * *', '09:00', 1, NULL, 0, 'exp');\"" 2>&1
        
        # Inject notification with empty ID (may fail due to NOT NULL constraint, but we try)
        print_info "  - Injecting notification with empty ID..."
        $ADB_BIN shell "run-as ${APP_ID} sqlite3 databases/daily_notification_plugin.db \"INSERT OR REPLACE INTO notification_content (id, title, body, scheduled_time, priority, vibration_enabled, sound_enabled, delivery_status, delivery_attempts, last_delivery_attempt, user_interaction_count, last_user_interaction, ttl_seconds, created_at, updated_at) VALUES ('', 'Test Invalid Notification', 'This has an empty ID', ${PAST_TIME}, 0, 1, 1, 'pending', 0, 0, 0, 0, 86400, ${NOW_TIME}, ${NOW_TIME});\"" 2>&1
        
        # Checkpoint WAL file to ensure changes are visible
        print_info "  - Checkpointing WAL file..."
        $ADB_BIN shell "run-as ${APP_ID} sqlite3 databases/daily_notification_plugin.db \"PRAGMA wal_checkpoint(FULL);\"" 2>&1
        
        # Verify data was inserted
        print_info "Verifying data injection..."
        SCHEDULE_COUNT=$($ADB_BIN shell "run-as ${APP_ID} sqlite3 databases/daily_notification_plugin.db \"SELECT COUNT(*) FROM schedules;\"" 2>&1 | tr -d '\r\n')
        NOTIFICATION_COUNT=$($ADB_BIN shell "run-as ${APP_ID} sqlite3 databases/daily_notification_plugin.db \"SELECT COUNT(*) FROM notification_content;\"" 2>&1 | tr -d '\r\n')
        
        print_info "  - Schedules in database: ${SCHEDULE_COUNT}"
        print_info "  - Notifications in database: ${NOTIFICATION_COUNT}"
        
        if [ "${SCHEDULE_COUNT}" -gt "0" ] 2>/dev/null; then
            print_success "✅ Invalid test data injected successfully"
            
            # Show what was inserted
            print_info "Inserted schedules:"
            $ADB_BIN shell "run-as ${APP_ID} sqlite3 databases/daily_notification_plugin.db \"SELECT id, kind, enabled, nextRunAt FROM schedules;\"" 2>&1 | while read line; do
                print_info "    $line"
            done
        else
            print_warn "⚠️  No schedules found after injection - data may not have been inserted"
        fi
        
        print_step "3" "Triggering recovery with invalid data..."
        $ADB_BIN shell am start -n "${APP_ID}/.MainActivity" > /dev/null 2>&1
        sleep 3  # Give recovery time to run
        
        print_info "Waiting for recovery to complete..."
        sleep 2
        
        print_step "4" "Checking recovery logs for invalid data handling..."
        
        # Check logs
        RECOVERY_LOGS=$($ADB_BIN logcat -d | grep -E "DNP-REACTIVATION|Skipping invalid|TEST:" | tail -30)
        
        echo ""
        print_info "Recovery logs:"
        echo "${RECOVERY_LOGS}"
        echo ""
        
        # Check for invalid data handling
        TEST4_PASSED=false
        TEST4_FAILED=false
        
        if echo "${RECOVERY_LOGS}" | grep -q "Skipping invalid"; then
            print_success "✅ Invalid data was detected and skipped"
            echo "${RECOVERY_LOGS}" | grep "Skipping invalid"
            TEST4_PASSED=true
        else
            print_warn "⚠️  No 'Skipping invalid' logs found"
            print_info "This could mean:"
            echo "  - Invalid data wasn't injected (database constraints prevented it)"
            echo "  - Recovery didn't encounter invalid data"
            echo "  - Logs were cleared"
            # Not a failure - constraints may have prevented injection
        fi
        
        if echo "${RECOVERY_LOGS}" | grep -q "recovery complete\|Recovery completed"; then
            print_success "✅ Recovery completed successfully"
            if [ "${TEST4_PASSED}" = "false" ]; then
                TEST4_PASSED=true  # Recovery completed = passed (even if no invalid data found)
            fi
        else
            print_warn "⚠️  Recovery completion message not found in logs"
        fi
        
        if echo "${RECOVERY_LOGS}" | grep -qiE "crash|fatal|exception.*recovery|Failed.*recovery"; then
            print_error "❌ TEST 4 FAILED: Recovery crashed or threw fatal exception"
            TEST4_FAILED=true
        fi
        
        # Final verdict
        if [ "${TEST4_FAILED}" = "true" ]; then
            print_error ""
            print_error "════════════════════════════════════════════════════════════"
            print_error "TEST 4 FINAL RESULT: ❌ FAILED"
            print_error "════════════════════════════════════════════════════════════"
            print_error "Reason: Recovery crashed or threw fatal exception"
            print_error "════════════════════════════════════════════════════════════"
        elif [ "${TEST4_PASSED}" = "true" ]; then
            print_success ""
            print_success "════════════════════════════════════════════════════════════"
            print_success "TEST 4 FINAL RESULT: ✅ PASSED"
            print_success "════════════════════════════════════════════════════════════"
            print_success "Recovery handled invalid data gracefully (or no invalid data found)"
            print_success "════════════════════════════════════════════════════════════"
        else
            print_warn ""
            print_warn "════════════════════════════════════════════════════════════"
            print_warn "TEST 4 FINAL RESULT: ⚠️  INCONCLUSIVE"
            print_warn "════════════════════════════════════════════════════════════"
            print_warn "Could not verify invalid data handling"
            print_warn "════════════════════════════════════════════════════════════"
        fi
        
    else
        print_info "App is not debuggable - using plugin API method"
        print_info "The plugin method 'injectInvalidTestData' can be called from JavaScript:"
        echo ""
        echo "  await window.DailyNotification.injectInvalidTestData({"
        echo "    injectEmptyScheduleId: true,"
        echo "    injectNullNextRunAt: true,"
        echo "    injectEmptyNotificationId: true"
        echo "  });"
        echo ""
        print_info "TEST 4: Code review confirms invalid data handling exists"
        print_info "  - ReactivationManager.kt checks for empty IDs (line 401, 439)"
        print_info "  - Errors are logged but don't crash recovery"
        print_info "  - Plugin method 'injectInvalidTestData' available for testing"
    fi
    
    # Cleanup
    rm -f "${TEST_SCRIPT}"
    
    wait_for_user
    fi
    
    # ============================================
    # Summary
    # ============================================
    print_header "Testing Complete"
    
    echo "Test Results Summary:"
    echo ""
    echo "TEST 1: Cold Start Missed Detection"
    echo "  - ✅ PASSED if logs show 'missed=1'"
    echo "  - ❌ FAILED if logs show 'missed=0' or no recovery logs"
    echo ""
    echo "TEST 2: Future Alarm Verification/Rescheduling"
    echo "  - ✅ PASSED if logs show 'rescheduled=1' OR 'verified=1'"
    echo "  - ℹ️  INFO if both are 0 (no future alarms to check)"
    echo ""
    echo "TEST 3: Recovery Timeout"
    echo "  - Timeout mechanism verified in code"
    echo ""
    echo "TEST 4: Invalid Data Handling"
    echo "  - Requires database access (debuggable app or root)"
    echo ""
    
    print_info "All recovery logs:"
    echo ""
    $ADB_BIN logcat -d | grep "$REACTIVATION_TAG" | tail -20
    echo ""
    
    print_success "Phase 1 testing script complete!"
    echo ""
    echo "Next steps:"
    echo "  - Review logs above"
    echo "  - Verify all tests passed"
    echo "  - Check database if needed (debuggable app)"
    echo "  - Update Doc B with test results"
}

# Run main function
main "$@"

