#!/bin/bash

# Immich Restore Script Test Suite
# This script tests the restoration functionality with mock data and validation

set -e

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Test configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TEST_DIR="${SCRIPT_DIR}/test_data"
RESTORE_SCRIPT="${SCRIPT_DIR}/restore-immich.sh"
TEST_LOG="${SCRIPT_DIR}/../logs/immich-restore-test.log"

# Test counters
TESTS_RUN=0
TESTS_PASSED=0
TESTS_FAILED=0

# Create test directory
mkdir -p "$TEST_DIR"
mkdir -p "$(dirname "$TEST_LOG")"

# Logging function
log_test() {
    local message="$1"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - TEST: $message" | tee -a "$TEST_LOG"
}

log_pass() {
    local test_name="$1"
    echo -e "${GREEN}✅ PASS${NC}: $test_name"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - PASS: $test_name" >> "$TEST_LOG"
    TESTS_PASSED=$((TESTS_PASSED + 1))
}

log_fail() {
    local test_name="$1"
    local details="$2"
    echo -e "${RED}❌ FAIL${NC}: $test_name"
    [ -n "$details" ] && echo "   Details: $details"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - FAIL: $test_name - $details" >> "$TEST_LOG"
    TESTS_FAILED=$((TESTS_FAILED + 1))
}

log_info() {
    local message="$1"
    echo -e "${BLUE}ℹ️  INFO${NC}: $message"
}

# Test script existence and permissions
test_script_setup() {
    TESTS_RUN=$((TESTS_RUN + 1))
    log_test "Script Setup Validation"

    if [ -f "$RESTORE_SCRIPT" ]; then
        if [ -x "$RESTORE_SCRIPT" ]; then
            log_pass "Script exists and is executable"
        else
            log_fail "Script exists but is not executable"
            chmod +x "$RESTORE_SCRIPT"
            log_info "Made script executable"
        fi
    else
        log_fail "Restore script not found at $RESTORE_SCRIPT"
        return 1
    fi
}

# Test help functionality
test_help_functionality() {
    TESTS_RUN=$((TESTS_RUN + 1))
    log_test "Help Functionality"

    local help_output
    if help_output=$("$RESTORE_SCRIPT" --help 2>&1); then
        if echo "$help_output" | grep -q "Usage:"; then
            log_pass "Help command works and shows usage"
        else
            log_fail "Help command runs but doesn't show proper usage"
        fi
    else
        log_fail "Help command failed to execute"
    fi
}

# Create mock backup files
create_mock_backups() {
    log_test "Creating mock backup files for testing"

    # Create mock database backup (gzipped SQL)
    local mock_db_backup="${TEST_DIR}/mock_immich_db_backup_20250603_120000.sql.gz"
    echo "-- Mock Immich Database Backup
CREATE DATABASE IF NOT EXISTS immich;
USE immich;
CREATE TABLE IF NOT EXISTS test_table (id INT PRIMARY KEY, name VARCHAR(100));
INSERT INTO test_table VALUES (1, 'test_data');
-- End of mock backup" | gzip > "$mock_db_backup"

    # Create mock uploads backup (tar.gz)
    local mock_uploads_backup="${TEST_DIR}/mock_immich_uploads_20250603_120000.tar.gz"
    mkdir -p "${TEST_DIR}/mock_uploads/upload"
    mkdir -p "${TEST_DIR}/mock_uploads/thumbs"
    echo "Mock photo data" > "${TEST_DIR}/mock_uploads/upload/photo1.jpg"
    echo "Mock thumbnail data" > "${TEST_DIR}/mock_uploads/thumbs/thumb1.jpg"

    tar -czf "$mock_uploads_backup" -C "${TEST_DIR}" mock_uploads

    # Create corrupted backup files for testing
    echo "corrupted data" > "${TEST_DIR}/corrupted_db.sql.gz"
    echo "not a tar file" > "${TEST_DIR}/corrupted_uploads.tar.gz"

    log_info "Mock backup files created"
    return 0
}

# Test dry-run functionality
test_dry_run() {
    TESTS_RUN=$((TESTS_RUN + 1))
    log_test "Dry Run Functionality"

    local mock_db_backup="${TEST_DIR}/mock_immich_db_backup_20250603_120000.sql.gz"
    local mock_uploads_backup="${TEST_DIR}/mock_immich_uploads_20250603_120000.tar.gz"

    local output
    if output=$("$RESTORE_SCRIPT" --db-backup "$mock_db_backup" --uploads-backup "$mock_uploads_backup" --dry-run 2>&1); then
        if echo "$output" | grep -q "DRY RUN MODE"; then
            log_pass "Dry run mode works correctly"
        else
            log_fail "Dry run executed but didn't show proper dry run message"
        fi
    else
        log_fail "Dry run command failed"
    fi
}

# Test file validation
test_file_validation() {
    TESTS_RUN=$((TESTS_RUN + 1))
    log_test "Backup File Validation"

    # Test with non-existent files
    local output
    if output=$("$RESTORE_SCRIPT" --db-backup "/nonexistent/file.sql.gz" --uploads-backup "/nonexistent/file.tar.gz" --dry-run 2>&1); then
        log_fail "Script should fail with non-existent files but didn't"
    else
        if echo "$output" | grep -q "not found"; then
            log_pass "File validation correctly detects missing files"
        else
            log_fail "Script failed but not with expected error message"
        fi
    fi
}

# Test corrupted file detection
test_corrupted_file_detection() {
    TESTS_RUN=$((TESTS_RUN + 1))
    log_test "Corrupted File Detection"

    local corrupted_db="${TEST_DIR}/corrupted_db.sql.gz"
    local corrupted_uploads="${TEST_DIR}/corrupted_uploads.tar.gz"

    local output
    if output=$("$RESTORE_SCRIPT" --db-backup "$corrupted_db" --uploads-backup "$corrupted_uploads" --dry-run 2>&1); then
        log_fail "Script should detect corrupted files but didn't"
    else
        if echo "$output" | grep -q "corrupted"; then
            log_pass "Corrupted file detection works"
        else
            log_fail "Script failed but not with corrupted file error"
        fi
    fi
}

# Test skip options
test_skip_options() {
    TESTS_RUN=$((TESTS_RUN + 1))
    log_test "Skip Options Functionality"

    # Test skip-db option
    local output
    if output=$("$RESTORE_SCRIPT" --uploads-backup "${TEST_DIR}/mock_immich_uploads_20250603_120000.tar.gz" --skip-db --dry-run 2>&1); then
        if echo "$output" | grep -q "Database backup: SKIPPED"; then
            log_pass "Skip database option works"
        else
            log_fail "Skip database option doesn't show correct status"
        fi
    else
        log_fail "Skip database option test failed"
    fi

    TESTS_RUN=$((TESTS_RUN + 1))

    # Test skip-uploads option
    if output=$("$RESTORE_SCRIPT" --db-backup "${TEST_DIR}/mock_immich_db_backup_20250603_120000.sql.gz" --skip-uploads --dry-run 2>&1); then
        if echo "$output" | grep -q "Uploads backup: SKIPPED"; then
            log_pass "Skip uploads option works"
        else
            log_fail "Skip uploads option doesn't show correct status"
        fi
    else
        log_fail "Skip uploads option test failed"
    fi
}

# Test environment variable validation
test_env_validation() {
    TESTS_RUN=$((TESTS_RUN + 1))
    log_test "Environment Variable Validation"

    # Temporarily move .env file to test missing env
    local env_file
    env_file="$(dirname "$RESTORE_SCRIPT")/../.env"
    if [ -f "$env_file" ]; then
        mv "$env_file" "${env_file}.backup"

        local output
        if output=$("$RESTORE_SCRIPT" --help 2>&1); then
            if echo "$output" | grep -q "Error.*env"; then
                log_pass "Missing environment file detection works"
            else
                log_fail "Script should detect missing .env file"
            fi
        else
            log_pass "Script correctly fails with missing .env file"
        fi

        # Restore .env file
        mv "${env_file}.backup" "$env_file"
    else
        log_info "No .env file found to test with"
    fi
}

# Test notification system (dry run)
test_notification_system() {
    TESTS_RUN=$((TESTS_RUN + 1))
    log_test "Notification System"

    local mock_db_backup="${TEST_DIR}/mock_immich_db_backup_20250603_120000.sql.gz"
    local mock_uploads_backup="${TEST_DIR}/mock_immich_uploads_20250603_120000.tar.gz"

    # Set a test webhook URL temporarily
    export WEBHOOK_URL="https://httpbin.org/post"

    local output
    if output=$("$RESTORE_SCRIPT" --db-backup "$mock_db_backup" --uploads-backup "$mock_uploads_backup" --dry-run 2>&1); then
        if echo "$output" | grep -q "Immich Restore Started"; then
            log_pass "Notification system appears to be working"
        else
            log_fail "Notification system not triggering properly"
        fi
    else
        log_fail "Test with notifications failed"
    fi

    unset WEBHOOK_URL
}

# Test argument parsing
test_argument_parsing() {
    TESTS_RUN=$((TESTS_RUN + 1))
    log_test "Argument Parsing"

    # Test unknown option
    local output
    if output=$("$RESTORE_SCRIPT" --unknown-option 2>&1); then
        if echo "$output" | grep -q "Unknown option"; then
            log_pass "Unknown option detection works"
        else
            log_fail "Unknown option should be detected"
        fi
    else
        log_pass "Script correctly fails with unknown option"
    fi
}

# Test logging functionality
test_logging() {
    TESTS_RUN=$((TESTS_RUN + 1))
    log_test "Logging Functionality"

    local log_dir
    log_dir="$(dirname "$RESTORE_SCRIPT")/../logs"
    local restore_log="${log_dir}/immich-restore.log"

    # Clear previous log entries
    [ -f "$restore_log" ] && true > "$restore_log"

    local mock_db_backup="${TEST_DIR}/mock_immich_db_backup_20250603_120000.sql.gz"
    local mock_uploads_backup="${TEST_DIR}/mock_immich_uploads_20250603_120000.tar.gz"

    "$RESTORE_SCRIPT" --db-backup "$mock_db_backup" --uploads-backup "$mock_uploads_backup" --dry-run >/dev/null 2>&1

    if [ -f "$restore_log" ] && [ -s "$restore_log" ]; then
        if grep -q "IMMICH RESTORATION STARTED" "$restore_log"; then
            log_pass "Logging functionality works"
        else
            log_fail "Log file exists but doesn't contain expected content"
        fi
    else
        log_fail "Log file not created or is empty"
    fi
}

# Performance test with larger mock files
test_performance() {
    TESTS_RUN=$((TESTS_RUN + 1))
    log_test "Performance with Larger Files"

    # Create a larger mock database backup
    local large_db_backup="${TEST_DIR}/large_mock_db.sql.gz"
    {
        echo "-- Large Mock Database Backup"
        for i in {1..1000}; do
            echo "INSERT INTO test_table VALUES ($i, 'test_data_$i');"
        done
        echo "-- End of large mock backup"
    } | gzip > "$large_db_backup"

    # Create larger mock uploads
    local large_uploads_backup="${TEST_DIR}/large_mock_uploads.tar.gz"
    mkdir -p "${TEST_DIR}/large_mock_uploads"
    for i in {1..50}; do
        echo "Mock large file content $i" > "${TEST_DIR}/large_mock_uploads/file_$i.txt"
    done
    tar -czf "$large_uploads_backup" -C "${TEST_DIR}" large_mock_uploads

    local start_time
    start_time=$(date +%s)
    local output
    if output=$("$RESTORE_SCRIPT" --db-backup "$large_db_backup" --uploads-backup "$large_uploads_backup" --dry-run 2>&1); then
        local end_time
        end_time=$(date +%s)
        local duration=$((end_time - start_time))

        if [ $duration -lt 30 ]; then  # Should complete dry run in under 30 seconds
            log_pass "Performance test completed in ${duration}s"
        else
            log_fail "Performance test took too long: ${duration}s"
        fi
    else
        log_fail "Performance test failed to execute"
    fi
}

# Cleanup test data
cleanup_test_data() {
    log_test "Cleaning up test data"
    rm -rf "$TEST_DIR"
    log_info "Test data cleaned up"
}

# Generate test report
generate_test_report() {
    echo ""
    echo "=================================================================="
    echo -e "${BLUE}IMMICH RESTORE SCRIPT TEST REPORT${NC}"
    echo "=================================================================="
    echo "Test Date: $(date)"
    echo "Script Tested: $RESTORE_SCRIPT"
    echo ""
    echo "Test Results:"
    echo -e "  Total Tests Run: ${BLUE}$TESTS_RUN${NC}"
    echo -e "  Tests Passed: ${GREEN}$TESTS_PASSED${NC}"
    echo -e "  Tests Failed: ${RED}$TESTS_FAILED${NC}"
    echo ""

    if [ $TESTS_FAILED -eq 0 ]; then
        echo -e "${GREEN}✅ ALL TESTS PASSED${NC}"
        echo "The restore script is ready for production use."
    else
        echo -e "${RED}❌ SOME TESTS FAILED${NC}"
        echo "Please review the test log for details: $TEST_LOG"
    fi

    echo ""
    echo "Test Log Location: $TEST_LOG"
    echo "=================================================================="
}

# Main test execution
main() {
    echo -e "${BLUE}Starting Immich Restore Script Test Suite${NC}"
    echo "Test Directory: $TEST_DIR"
    echo "Log File: $TEST_LOG"
    echo ""

    # Initialize test log
    echo "=== Immich Restore Script Test Suite ===" > "$TEST_LOG"
    echo "Started: $(date)" >> "$TEST_LOG"
    echo "" >> "$TEST_LOG"

    # Run all tests
    test_script_setup
    create_mock_backups
    test_help_functionality
    test_dry_run
    test_file_validation
    test_corrupted_file_detection
    test_skip_options
    test_env_validation
    test_notification_system
    test_argument_parsing
    test_logging
    test_performance

    # Cleanup and report
    cleanup_test_data
    generate_test_report

    # Exit with appropriate code
    if [ $TESTS_FAILED -eq 0 ]; then
        exit 0
    else
        exit 1
    fi
}

# Run tests
main "$@"
