#!/usr/bin/env bash

set -euo pipefail
IFS=$'\n\t'

# ========================================
# Phase 2 Testing Script – Force Stop Recovery
# ========================================

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

# Initialize run directory (P1)
ensure_run_dir || {
  error "Failed to initialize run directory"
  exit 1
}

# Phase 2 specific configuration
# Log tags / patterns (matched to actual ReactivationManager logs)
FORCE_STOP_SCENARIO_VALUE="FORCE_STOP"
COLD_START_SCENARIO_VALUE="COLD_START"
NONE_SCENARIO_VALUE="NONE"
BOOT_SCENARIO_VALUE="BOOT"

# Strictness policy (P3.2)
# soft: minor device quirks = warn (default, for development)
# hard: any unexpected alarm loss / missed schedule = fail (for release gating)
: "${STRICTNESS:=soft}"

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

# ------------------------------------------------------------------------------
# TEST 1 – Force Stop with Cleared Alarms
# ------------------------------------------------------------------------------

test1_force_stop_cleared_alarms() {
  section "TEST 1: Force Stop – Alarms Cleared"

  # Set test context
  set_test_context "phase2" "phase2_test1" ""

  info "Purpose: Verify force stop detection and alarm rescheduling when alarms are cleared."
  info "Expected time: 5-8 minutes"
  info "Automatable: Partial (requires manual force-stop verification)"
  echo ""

  pause

  # Capture initial state
  set_test_context "phase2" "phase2_test1" "p2_t1_s1"
  step_start "p2_t1_s1" "Launch app & check plugin status"
  capture_alarms "phase2_test1_initial"
  capture_logcat "phase2_test1_initial" "DNP" 50

  substep "Step 1: Launch app & check plugin status"
  launch_app

  ui_prompt "1) In the app UI, verify plugin status:

  ⚙️ Plugin Settings: ✅ Configured
  🔌 Native Fetcher: ✅ Configured

  If either shows ❌ or 'Not configured', click 'Configure Plugin', wait until both are ✅, then press Enter."

  ui_prompt "2) Now schedule at least one future notification (e.g., click 'Test Notification' to schedule for a few minutes in the future)."

  step_pass "p2_t1_s1" "Plugin configured and notification scheduled"

  # Capture before force-stop state
  capture_alarms "phase2_test1_before_force_stop"

  substep "Step 2: Verify alarms are scheduled"
  set_test_context "phase2" "phase2_test1" "p2_t1_s2"
  step_start "p2_t1_s2" "Verify alarms scheduled"
  show_alarms
  local before_count system_count
  before_count="$(get_plugin_alarm_count)"
  system_count="$(get_system_alarm_count)"
  info "Plugin alarms before force stop: $before_count (expected: 1)"
  info "System/other alarms: $system_count (for context)"

  if [[ "$before_count" -eq 0 ]]; then
    warn "No plugin alarms found before force stop; TEST 1 may not be meaningful."
    step_warn "p2_t1_s2" "No alarms found"
  elif [[ "$before_count" -eq 1 ]]; then
    ok "Single plugin alarm confirmed (one per day)"
    step_pass "p2_t1_s2" "Alarms verified"
  else
    warn "Found $before_count plugin alarms (expected: 1)"
    step_warn "p2_t1_s2" "Unexpected alarm count"
  fi

  pause

  substep "Step 3: Force stop app (should clear alarms on many devices)"
  set_test_context "phase2" "phase2_test1" "p2_t1_s3"
  step_start "p2_t1_s3" "Force stop app"
  force_stop_app

  # Capture after force-stop state
  capture_alarms "phase2_test1_after_force_stop"
  step_pass "p2_t1_s3" "App force stopped"

  substep "Step 4: Check alarms after force stop"
  set_test_context "phase2" "phase2_test1" "p2_t1_s4"
  step_start "p2_t1_s4" "Check alarms after force stop"
  local after_count system_after
  after_count="$(get_plugin_alarm_count)"
  system_after="$(get_system_alarm_count)"
  info "Plugin alarms after force stop: $after_count (expected: 0)"
  info "System/other alarms: $system_after (for context)"
  show_alarms

  if [[ "$after_count" -gt 0 ]]; then
    if [[ "$STRICTNESS" == "hard" ]]; then
      error "Plugin alarms still present after force stop (strict mode: hard)"
      step_fail "p2_t1_s4" "Alarms not cleared"
    else
      warn "Plugin alarms still present after force stop. This device/OS may not clear alarms on force stop."
      warn "TEST 1 will continue but may not fully validate FORCE_STOP scenario."
      step_warn "p2_t1_s4" "Alarms may not be cleared (device-specific)"
    fi
  else
    step_pass "p2_t1_s4" "Alarms cleared"
  fi

  pause

  substep "Step 4.5: Clear boot flag (prevent false BOOT detection)"
  # Clear boot flag to ensure force stop detection works correctly
  # Boot flag might be set from previous runs or emulator quirks
  $ADB_BIN shell "run-as ${APP_ID} rm -f shared_prefs/dailynotification_recovery.xml 2>/dev/null || true"
  info "Boot flag cleared (if it existed)"

  substep "Step 5: Launch app (triggers recovery) and capture logs"
  set_test_context "phase2" "phase2_test1" "p2_t1_s5"
  step_start "p2_t1_s5" "Relaunch app & verify recovery"
  clear_logs
  launch_app
  sleep 5  # give recovery a moment to run

  # Capture after recovery state
  capture_alarms "phase2_test1_after_recovery"
  capture_logcat "phase2_test1_after_recovery" "DNP-REACTIVATION" 250
  capture_screenshot "phase2_test1_after_recovery"

  info "Collecting recovery logs..."
  local logs
  logs="$(get_recovery_logs)"
  echo "$logs"

  local scenario rescheduled verified errors
  scenario="$(extract_scenario_from_logs "$logs")"
  rescheduled="$(extract_field_from_logs "$logs" "rescheduled")"
  verified="$(extract_field_from_logs "$logs" "verified")"
  errors="$(extract_field_from_logs "$logs" "errors")"

  echo
  info "Parsed recovery summary:"
  echo "  scenario   = ${scenario:-<none>}"
  echo "  rescheduled= ${rescheduled}"
  echo "  verified   = ${verified}"
  echo "  errors     = ${errors}"
  echo

  # Determine verdict based on STRICTNESS policy
  local test1_passed=false
  local test1_message=""

  if [[ "$errors" -gt 0 ]]; then
    error "Recovery reported errors>0 (errors=$errors)"
    if [[ "$STRICTNESS" == "hard" ]]; then
      test1_message="Recovery reported errors (errors=$errors)"
    else
      test1_message="Recovery reported errors but continuing (errors=$errors, strictness=soft)"
    fi
  fi

  if [[ "$scenario" == "$FORCE_STOP_SCENARIO_VALUE" && "$rescheduled" -gt 0 ]]; then
    ok "TEST 1 PASSED: Force stop detected and alarms rescheduled (scenario=$scenario, rescheduled=$rescheduled)."
    test1_passed=true
    test1_message="Force stop detected and alarms rescheduled (scenario=$scenario, rescheduled=$rescheduled)"
  elif [[ "$scenario" == "$FORCE_STOP_SCENARIO_VALUE" && "$rescheduled" -eq 0 ]]; then
    if [[ "$STRICTNESS" == "hard" ]]; then
      test1_message="scenario=FORCE_STOP but rescheduled=0 (strict mode: hard)"
    else
      warn "TEST 1: scenario=FORCE_STOP but rescheduled=0. Check implementation or logs."
      test1_message="scenario=FORCE_STOP but rescheduled=0 (strictness=soft)"
    fi
  elif [[ "$after_count" -gt 0 ]]; then
    info "TEST 1: Device/emulator kept alarms after force stop; FORCE_STOP scenario may not trigger here."
    if [[ "$rescheduled" -gt 0 ]]; then
      info "Recovery still worked (rescheduled=$rescheduled), but scenario was ${scenario:-COLD_START} instead of FORCE_STOP"
      test1_passed=true
      test1_message="Recovery worked but FORCE_STOP scenario not detected (device kept alarms, rescheduled=$rescheduled, scenario=${scenario:-COLD_START})"
    else
      if [[ "$STRICTNESS" == "hard" ]]; then
        test1_message="Device kept alarms but recovery didn't reschedule (strict mode: hard)"
      else
        test1_message="Device kept alarms, FORCE_STOP scenario may not trigger (strictness=soft)"
      fi
    fi
  else
    if [[ "$STRICTNESS" == "hard" ]]; then
      test1_message="Expected FORCE_STOP scenario not detected (strict mode: hard, scenario=${scenario:-<none>}, rescheduled=$rescheduled)"
    else
      warn "TEST 1: Expected FORCE_STOP scenario not clearly detected. Review logs and scenario detection logic."
      info "Scenario detected: ${scenario:-<none>}, rescheduled=$rescheduled"
      test1_message="FORCE_STOP scenario not clearly detected (scenario=${scenario:-<none>}, rescheduled=$rescheduled, strictness=soft)"
    fi
  fi

  # Emit verdict
  if [[ "$test1_passed" == "true" ]]; then
    step_pass "p2_t1_s5" "Recovery successful"
  else
    step_fail "p2_t1_s5" "Recovery failed or inconclusive"
  fi

  set_test_context "phase2" "phase2_test1" "p2_t1_s6"
  if [[ "$test1_passed" == "true" ]]; then
    verdict_pass "phase2_test1_force_stop_cleared" "$test1_message"
  elif [[ "$STRICTNESS" == "hard" ]]; then
    verdict_fail "phase2_test1_force_stop_cleared" "$test1_message"
  else
    verdict_warn "phase2_test1_force_stop_cleared" "$test1_message"
  fi

  evidence_block "phase2_test1_force_stop_cleared"

  substep "Step 6: Verify alarms are rescheduled in AlarmManager"
  show_alarms
}

# ------------------------------------------------------------------------------
# TEST 2 – Force Stop / Process Stop with Intact Alarms
# ------------------------------------------------------------------------------

test2_force_stop_intact_alarms() {
  section "TEST 2: Force Stop / Process Stop – Alarms Intact"

  # Set test context
  set_test_context "phase2" "phase2_test2" ""

  info "Purpose: Verify that heavy FORCE_STOP recovery does not run when alarms are still present."
  info "Expected time: 4-6 minutes"
  info "Automatable: Partial (requires manual verification)"
  echo ""

  pause

  # Capture initial state
  set_test_context "phase2" "phase2_test2" "p2_t2_s1"
  step_start "p2_t2_s1" "Schedule notification"
  capture_alarms "phase2_test2_initial"
  capture_logcat "phase2_test2_initial" "DNP" 50

  substep "Step 1: Launch app & schedule notifications"
  launch_app
  ui_prompt "1) In the app UI, ensure plugin is configured and schedule at least one future notification.

  Press Enter when done."

  step_pass "p2_t2_s1" "Notification scheduled"

  # Capture before soft stop state
  capture_alarms "phase2_test2_before_soft_stop"

  substep "Step 2: Verify alarms are scheduled"
  set_test_context "phase2" "phase2_test2" "p2_t2_s2"
  step_start "p2_t2_s2" "Force stop app"
  show_alarms
  local before system_before
  before="$(get_plugin_alarm_count)"
  system_before="$(get_system_alarm_count)"
  info "Plugin alarms before stop: $before (expected: 1)"
  info "System/other alarms: $system_before (for context)"

  if [[ "$before" -eq 0 ]]; then
    warn "No plugin alarms found; TEST 2 may not be meaningful."
    step_warn "p2_t2_s2" "No alarms found"
  elif [[ "$before" -eq 1 ]]; then
    ok "Single plugin alarm confirmed (one per day)"
    step_pass "p2_t2_s2" "Alarms verified"
  else
    warn "Found $before plugin alarms (expected: 1)"
    step_warn "p2_t2_s2" "Unexpected alarm count"
  fi

  pause

  substep "Step 3: Simulate a 'soft' stop or process kill that does NOT clear alarms"
  set_test_context "phase2" "phase2_test2" "p2_t2_s2"
  step_start "p2_t2_s2" "Force stop app"
  info "Killing app process (non-destructive - may not clear alarms)..."
  $ADB_BIN shell am kill "$APP_ID" || true
  sleep 2
  ok "Kill signal sent (soft stop)"
  step_pass "p2_t2_s2" "App force stopped"

  # Capture after soft stop state
  capture_alarms "phase2_test2_after_soft_stop"

  substep "Step 4: Verify alarms are still scheduled"
  set_test_context "phase2" "phase2_test2" "p2_t2_s3"
  step_start "p2_t2_s3" "Verify alarms intact"
  local after system_after
  after="$(get_plugin_alarm_count)"
  system_after="$(get_system_alarm_count)"
  info "Plugin alarms after soft stop: $after (expected: 1)"
  info "System/other alarms: $system_after (for context)"
  show_alarms

  if [[ "$after" -eq 0 ]]; then
    if [[ "$STRICTNESS" == "hard" ]]; then
      error "Alarms cleared after soft stop (strict mode: hard)"
      step_fail "p2_t2_s3" "Alarms cleared"
    else
      warn "Alarms appear cleared after soft stop; this environment may not distinguish TEST 2 well."
      step_warn "p2_t2_s3" "Alarms may be cleared"
    fi
  else
    step_pass "p2_t2_s3" "Alarms intact"
  fi

  pause

  substep "Step 5: Relaunch app and check recovery logs"
  set_test_context "phase2" "phase2_test2" "p2_t2_s4"
  step_start "p2_t2_s4" "Relaunch & verify behavior"
  clear_logs
  launch_app
  sleep 5

  # Capture after recovery state
  capture_alarms "phase2_test2_after_recovery"
  capture_logcat "phase2_test2_after_recovery" "DNP-REACTIVATION" 250
  capture_screenshot "phase2_test2_after_recovery"

  info "Collecting recovery logs..."
  local logs
  logs="$(get_recovery_logs)"
  echo "$logs"

  local scenario rescheduled missed verified errors
  scenario="$(extract_scenario_from_logs "$logs")"
  rescheduled="$(extract_field_from_logs "$logs" "rescheduled")"
  missed="$(extract_field_from_logs "$logs" "missed")"
  verified="$(extract_field_from_logs "$logs" "verified")"
  errors="$(extract_field_from_logs "$logs" "errors")"

  echo
  info "Parsed recovery summary:"
  echo "  scenario   = ${scenario:-<none>}"
  echo "  rescheduled= ${rescheduled}"
  echo "  missed     = ${missed}"
  echo "  verified   = ${verified}"
  echo "  errors     = ${errors}"
  echo

  # Determine verdict based on STRICTNESS policy
  local test2_passed=false
  local test2_message=""

  if [[ "$errors" -gt 0 ]]; then
    error "Recovery reported errors>0 (errors=$errors)"
    if [[ "$STRICTNESS" == "hard" ]]; then
      test2_message="Recovery reported errors (errors=$errors)"
    else
      test2_message="Recovery reported errors but continuing (errors=$errors, strictness=soft)"
    fi
  fi

  if [[ "$after" -gt 0 && "$rescheduled" -eq 0 && "$scenario" != "$FORCE_STOP_SCENARIO_VALUE" ]]; then
    ok "TEST 2 PASSED: Alarms remained intact, and FORCE_STOP scenario did not run (scenario=$scenario, rescheduled=0)."
    test2_passed=true
    test2_message="Alarms remained intact, FORCE_STOP scenario did not run (scenario=$scenario, rescheduled=0)"
  else
    if [[ "$STRICTNESS" == "hard" ]]; then
      if [[ "$after" -eq 0 ]]; then
        test2_message="Alarms were cleared but should have remained (strict mode: hard)"
      elif [[ "$rescheduled" -gt 0 ]]; then
        test2_message="FORCE_STOP recovery ran when alarms were intact (strict mode: hard, scenario=$scenario, rescheduled=$rescheduled)"
      else
        test2_message="Unexpected state (strict mode: hard, scenario=$scenario, rescheduled=$rescheduled, after=$after)"
      fi
    else
      warn "TEST 2: Verify that FORCE_STOP recovery didn't misfire when alarms were intact."
      info "Scenario=${scenario:-<none>}, rescheduled=$rescheduled, after_count=$after"
      test2_message="FORCE_STOP recovery may have misfired (scenario=$scenario, rescheduled=$rescheduled, after=$after, strictness=soft)"
    fi
  fi

  if [[ "$test2_passed" == "true" ]]; then
    step_pass "p2_t2_s4" "Recovery behavior correct"
  else
    step_fail "p2_t2_s4" "Recovery behavior incorrect"
  fi

  # Emit verdict
  set_test_context "phase2" "phase2_test2" "p2_t2_s5"
  if [[ "$test2_passed" == "true" ]]; then
    verdict_pass "phase2_test2_force_stop_intact" "$test2_message"
  elif [[ "$STRICTNESS" == "hard" ]]; then
    verdict_fail "phase2_test2_force_stop_intact" "$test2_message"
  else
    verdict_warn "phase2_test2_force_stop_intact" "$test2_message"
  fi

  evidence_block "phase2_test2_force_stop_intact"
}

# ------------------------------------------------------------------------------
# TEST 3 – First Launch / Empty DB Safeguard
# ------------------------------------------------------------------------------

test3_first_launch_no_schedules() {
  section "TEST 3: First Launch / No Schedules Safeguard"

  # Set test context
  set_test_context "phase2" "phase2_test3" ""

  info "Purpose: Ensure force-stop recovery is NOT triggered when DB is empty or plugin isn't configured."
  info "Expected time: 3-5 minutes"
  info "Automatable: Yes"
  echo ""

  pause

  # Capture initial state (before uninstall)
  set_test_context "phase2" "phase2_test3" "p2_t3_s1"
  step_start "p2_t3_s1" "Fresh install"
  capture_alarms "phase2_test3_initial"

  substep "Step 1: Uninstall app to clear DB/state"
  set +e
  $ADB_BIN uninstall "$APP_ID" >/dev/null 2>&1
  set -e
  ok "App uninstalled (state cleared)"

  substep "Step 2: Reinstall app"
  if $ADB_BIN install -r "$APK_PATH"; then
    ok "App installed"
    step_pass "p2_t3_s1" "Fresh install complete"
  else
    error "Reinstall failed"
    step_fail "p2_t3_s1" "Reinstall failed"
    exit 1
  fi

  info "Clearing logcat..."
  clear_logs
  ok "Logs cleared"

  pause

  substep "Step 3: Launch app for the first time"
  set_test_context "phase2" "phase2_test3" "p2_t3_s2"
  step_start "p2_t3_s2" "Launch app & verify no recovery"
  launch_app
  sleep 5

  # Capture after first launch state
  capture_alarms "phase2_test3_after_first_launch"
  capture_logcat "phase2_test3_after_first_launch" "DNP-REACTIVATION" 250
  capture_screenshot "phase2_test3_after_first_launch"

  substep "Step 4: Collect logs and ensure no force-stop recovery ran"
  set_test_context "phase2" "phase2_test3" "p2_t3_s3"
  step_start "p2_t3_s3" "Verify no recovery ran"
  local logs
  logs="$(get_recovery_logs)"
  echo "$logs"

  local scenario rescheduled
  scenario="$(extract_scenario_from_logs "$logs")"
  rescheduled="$(extract_field_from_logs "$logs" "rescheduled")"

  echo
  info "Parsed summary:"
  echo "  scenario   = ${scenario:-<none>}"
  echo "  rescheduled= ${rescheduled}"
  echo

  # Determine verdict based on STRICTNESS policy
  local test3_passed=false
  local test3_message=""

  if [[ -z "$logs" ]]; then
    ok "TEST 3 PASSED: No force-stop recovery logs on first launch."
    test3_passed=true
    test3_message="No force-stop recovery logs on first launch (expected behavior)"
  elif [[ "$scenario" == "$NONE_SCENARIO_VALUE" && "$rescheduled" -eq 0 ]]; then
    ok "TEST 3 PASSED: NONE scenario logged with rescheduled=0 on first launch."
    test3_passed=true
    test3_message="NONE scenario logged with rescheduled=0 on first launch (expected behavior)"
  elif [[ "$rescheduled" -gt 0 ]]; then
    if [[ "$STRICTNESS" == "hard" ]]; then
      test3_message="rescheduled>0 on first launch / empty DB - force-stop recovery misfired (strict mode: hard, rescheduled=$rescheduled)"
    else
      warn "TEST 3: rescheduled>0 on first launch / empty DB. Check that force-stop recovery isn't misfiring."
      test3_message="rescheduled>0 on first launch (rescheduled=$rescheduled, strictness=soft)"
    fi
  else
    if [[ "$STRICTNESS" == "hard" ]]; then
      test3_message="Logs present but scenario unclear (strict mode: hard, scenario=${scenario:-<none>}, rescheduled=$rescheduled)"
    else
      info "TEST 3: Logs present but no rescheduling; review scenario handling to ensure it's explicit about NONE / FIRST_LAUNCH."
      test3_passed=true  # Not a failure, just needs review
      test3_message="Logs present but no rescheduling (scenario=${scenario:-<none>}, rescheduled=$rescheduled, strictness=soft)"
    fi
  fi

  if [[ "$test3_passed" == "true" ]]; then
    step_pass "p2_t3_s3" "No recovery ran (correct)"
  else
    step_fail "p2_t3_s3" "Recovery ran when it shouldn't"
  fi

  # Emit verdict
  set_test_context "phase2" "phase2_test3" "p2_t3_s4"
  if [[ "$test3_passed" == "true" ]]; then
    verdict_pass "phase2_test3_first_launch_no_schedules" "$test3_message"
  elif [[ "$STRICTNESS" == "hard" ]]; then
    verdict_fail "phase2_test3_first_launch_no_schedules" "$test3_message"
  else
    verdict_warn "phase2_test3_first_launch_no_schedules" "$test3_message"
  fi

  evidence_block "phase2_test3_first_launch_no_schedules"
}

# ------------------------------------------------------------------------------
# Main
# ------------------------------------------------------------------------------

main() {
  # Allow selecting specific tests: e.g. `./test-phase2.sh 1 3`
  if [[ "$#" -gt 0 && ( "$1" == "-h" || "$1" == "--help" ) ]]; then
    echo "Usage: $0 [TEST_IDS...] [STRICTNESS=soft|hard]"
    echo
    echo "If no TEST_IDS are given, all tests (1, 2, 3) will run."
    echo
    echo "STRICTNESS policy (P3.2):"
    echo "  soft (default): minor device quirks = warn"
    echo "  hard: any unexpected alarm loss / missed schedule = fail"
    echo
    echo "Examples:"
    echo "  $0                    # run all tests (soft mode)"
    echo "  $0 1                  # run only TEST 1 (soft mode)"
    echo "  $0 2 3                # run only TEST 2 and TEST 3 (soft mode)"
    echo "  STRICTNESS=hard $0    # run all tests (hard mode, release gating)"
    return 0
  fi

  SELECTED_TESTS=("$@")

  section "Phase 2 Testing Script – Force Stop Recovery"
  
  info "Mode: Standard"
  info "Strictness: ${STRICTNESS} (soft=warn on quirks, hard=fail on issues)"
  info "Run ID: ${RUN_ID}"
  info "Evidence directory: $(get_run_dir)"
  echo ""
  info "This script will guide you through Phase 2 tests."
  info "You'll be prompted when UI interaction is needed."
  echo ""

  pause

  require_adb_device
  build_app
  install_app

  if should_run_test "1" SELECTED_TESTS; then
    test1_force_stop_cleared_alarms
    pause
  fi

  if should_run_test "2" SELECTED_TESTS; then
    test2_force_stop_intact_alarms
    pause
  fi

  if should_run_test "3" SELECTED_TESTS; then
    test3_first_launch_no_schedules
  fi

  section "Testing Complete"

  info "Test Results Summary:"
  echo ""
  echo "All test verdicts are shown above with evidence locations."
  echo "Review evidence in: $(get_run_dir)"
  echo ""
  echo "Strictness mode: ${STRICTNESS}"
  echo "  - soft: Minor device quirks treated as warnings"
  echo "  - hard: Any unexpected behavior treated as failures"
  echo ""

  ok "Phase 2 testing script complete!"
  echo ""
  echo "Next steps:"
  echo "  - Review evidence in: $(get_run_dir)"
  echo "  - Verify all test verdicts above"
  echo "  - Update documentation with test results"
  echo ""
}

main "$@"
