#!/usr/bin/env bash
# CamSwapper HAL Hook - Integration Testing Script
# Tests the system-wide camera HAL hook installation and functionality
# Usage: ./test_hal_wrapper.sh [DEVICE_SERIAL]
#
# Prerequisites:
#   - adb installed and in PATH
#   - Device connected via USB (or specify serial with argument)
#   - Device rooted with Magisk or KernelSU
#   - Root module installed (root-module/ pushed to /data/adb/modules/camera2magic/)
#   - Device rebooted after module installation

set -euo pipefail

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# Test results
PASS_COUNT=0
FAIL_COUNT=0
RESULTS_LOG="test_results.log"

# ADB setup
ADB="adb"
if [ -n "${1:-}" ]; then
    ADB="adb -s $1"
fi

log() {
    echo -e "$*"
    echo -e "$*" >> "$RESULTS_LOG"
}

pass() {
    log "${GREEN}[PASS]${NC} $*"
    ((PASS_COUNT++))
}

fail() {
    log "${RED}[FAIL]${NC} $*"
    ((FAIL_COUNT++))
}

warn() {
    log "${YELLOW}[WARN]${NC} $*"
}

# Initialize results log
echo "CamSwapper HAL Hook - Integration Test Results" > "$RESULTS_LOG"
echo "Date: $(date)" >> "$RESULTS_LOG"
echo "=========================================" >> "$RESULTS_LOG"

log "========================================="
log "CamSwapper HAL Hook - Integration Test"
log "========================================="
log ""

# Test 0: Device connectivity
log "--- Test 0: Device Connectivity ---"
if $ADB shell "echo connected" >/dev/null 2>&1; then
    pass "Device connected via adb"
else
    fail "Device not connected. Check USB connection and adb authorization."
    log "Cannot continue without device connection."
    exit 1
fi

# Test 1: Root access
log ""
log "--- Test 1: Root Access ---"
ROOT_CHECK=$($ADB shell "su -c id" 2>/dev/null || true)
if echo "$ROOT_CHECK" | grep -q "uid=0"; then
    pass "Root access available"
else
    fail "Root access not available. Device must be rooted with Magisk or KernelSU."
    log "Cannot continue without root."
    exit 1
fi

# Test 2: Module installed
log ""
log "--- Test 2: Root Module Installation ---"
MODULE_DIR=$($ADB shell "su -c 'ls -d /data/adb/modules/camera2magic 2>/dev/null || ls -d /data/adb/modules/*camera* 2>/dev/null'" 2>/dev/null | tr -d '\r' || true)
if [ -n "$MODULE_DIR" ]; then
    pass "Module directory found: $MODULE_DIR"

    # Check hook library
    HOOK_LIB=$($ADB shell "su -c 'ls $MODULE_DIR/libcamera_hook.so 2>/dev/null'" 2>/dev/null | tr -d '\r' || true)
    if [ -n "$HOOK_LIB" ]; then
        pass "libcamera_hook.so present in module"
    else
        fail "libcamera_hook.so NOT found in module directory"
    fi

    # Check sepolicy.rule
    SEPOLICY=$($ADB shell "su -c 'ls $MODULE_DIR/sepolicy.rule 2>/dev/null'" 2>/dev/null | tr -d '\r' || true)
    if [ -n "$SEPOLICY" ]; then
        pass "sepolicy.rule present in module"
    else
        warn "sepolicy.rule not found (may not be required on all devices)"
    fi
else
    fail "Module directory not found in /data/adb/modules/"
    warn "Install the module: adb push root-module/ /data/adb/modules/camera2magic/"
fi

# Test 3: Wrap property set
log ""
log "--- Test 3: Wrap Property Configuration ---"
WRAP_PROP=$($ADB shell "getprop wrap.android.hardware.camera.provider@2.7-service-google" 2>/dev/null | tr -d '\r' || true)
if echo "$WRAP_PROP" | grep -q "LD_PRELOAD"; then
    pass "Wrap property set: $WRAP_PROP"
else
    fail "Wrap property NOT set or empty"
    warn "Expected: LD_PRELOAD=/data/adb/modules/.../libcamera_hook.so"
    warn "Try: adb shell setprop wrap.android.hardware.camera.provider@2.7-service-google 'LD_PRELOAD=/data/adb/modules/camera2magic/libcamera_hook.so'"
fi

# Test 4: Config file
log ""
log "--- Test 4: Configuration File ---"
CONFIG=$($ADB shell "su -c 'cat /data/local/camera_magic/config.txt 2>/dev/null'" 2>/dev/null | tr -d '\r' || true)
if [ -n "$CONFIG" ]; then
    pass "Config file exists"
    log "  Contents: $CONFIG"
else
    warn "Config file not found at /data/local/camera_magic/config.txt"
    warn "Creating default config..."
    $ADB shell "su -c 'mkdir -p /data/local/camera_magic && echo \"enabled=0\" > /data/local/camera_magic/config.txt && chmod 644 /data/local/camera_magic/config.txt'" 2>/dev/null || true
    pass "Default config created"
fi

# Test 5: Camera provider process detection
log ""
log "--- Test 5: Camera Provider Process ---"
PROVIDER_PID=$($ADB shell "pidof android.hardware.camera.provider@2.7-service-google" 2>/dev/null | tr -d '\r' || true)
if [ -n "$PROVIDER_PID" ]; then
    pass "Camera provider process running (PID: $PROVIDER_PID)"

    # Check if hook library is loaded
    LOADED_LIBS=$($ADB shell "su -c 'cat /proc/$PROVIDER_PID/maps 2>/dev/null | grep libcamera_hook'" 2>/dev/null | tr -d '\r' || true)
    if [ -n "$LOADED_LIBS" ]; then
        pass "libcamera_hook.so loaded in camera provider process"
    else
        warn "libcamera_hook.so NOT detected in camera provider process maps"
        warn "This may be normal if the provider hasn't been restarted since module install"
        warn "Try rebooting the device or restarting the camera provider"
    fi
else
    warn "Camera provider process not found (may not be running yet)"
    warn "The provider starts on-demand when a camera app is opened"
fi

# Test 6: SELinux status
log ""
log "--- Test 6: SELinux Status ---"
SELINUX_STATUS=$($ADB shell "getenforce" 2>/dev/null | tr -d '\r' || true)
if [ "$SELINUX_STATUS" = "Enforcing" ]; then
    pass "SELinux is Enforcing (policy rules are active)"
elif [ "$SELINUX_STATUS" = "Permissive" ]; then
    warn "SELinux is Permissive (policy rules not enforced, but hook should still work)"
else
    warn "SELinux status unknown: $SELINUX_STATUS"
fi

# Test 7: AVC denials check
log ""
log "--- Test 7: SELinux AVC Denials ---"
AVC_DENIALS=$($ADB shell "su -c 'dmesg | grep \"avc: denied\" | grep -i camera | tail -5'" 2>/dev/null | tr -d '\r' || true)
if [ -z "$AVC_DENIALS" ]; then
    pass "No camera-related AVC denials found"
else
    warn "AVC denials detected (may need additional SELinux rules):"
    log "$AVC_DENIALS"
fi

# Test 8: Logcat hook initialization
log ""
log "--- Test 8: Hook Initialization Logs ---"
HOOK_LOGS=$($ADB logcat -d -s CameraHook 2>/dev/null | grep -i "hook\|init\|loaded\|CameraHook" | tail -5 || true)
if [ -n "$HOOK_LOGS" ]; then
    pass "Hook initialization logs found"
    log "$HOOK_LOGS"
else
    warn "No hook initialization logs found"
    warn "This may be normal if the camera provider hasn't been restarted"
fi

# Summary
log ""
log "========================================="
log "Test Summary"
log "========================================="
log "${GREEN}Passed: $PASS_COUNT${NC}"
log "${RED}Failed: $FAIL_COUNT${NC}"
log ""

if [ "$FAIL_COUNT" -eq 0 ]; then
    log "${GREEN}All tests passed!${NC}"
    log ""
    log "Next steps:"
    log "1. Enable HAL mode in CamSwapper app"
    log "2. Set video path or RTSP URL in config"
    log "3. Open any camera app to verify virtual feed"
    log "4. Check: adb logcat -s CameraHook for frame injection logs"
else
    log "${RED}Some tests failed. Review the output above.${NC}"
    log ""
    log "Common fixes:"
    log "- Reboot device after module installation"
    log "- Verify module is in /data/adb/modules/camera2magic/"
    log "- Check wrap property is set correctly"
    log "- Ensure SELinux policy rules are loaded"
fi

log ""
log "Full results saved to: $RESULTS_LOG"

exit "$FAIL_COUNT"
