#include "log_test.h"
#include "storage.h"
#include "esp_partition.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_task_wdt.h"
#include <string.h>
#include <stdio.h>

#define TAG "LOG_TEST"

// External declarations for functions we need to add to storage.c
extern esp_err_t log_erase_all_sectors(void);
extern esp_err_t log_simulate_power_cycle(void);
extern esp_err_t log_read(uint8_t* len, uint8_t* buf, uint8_t* type);
extern void log_read_reset(void);

// Helper to wait for log queue to clear
static void wait_for_log_queue(void) {
    // Wait for all queued log entries to be written
    // The queue size is LOG_QUEUE_SIZE (8), so we wait a bit longer
    vTaskDelay(pdMS_TO_TICKS(500));
    esp_task_wdt_reset();
}

// Helper to compare two byte arrays
static bool arrays_equal(const uint8_t* a, const uint8_t* b, size_t len) {
    for (size_t i = 0; i < len; i++) {
        if (a[i] != b[i]) {
            ESP_LOGE(TAG, "Array mismatch at index %d: expected 0x%02X, got 0x%02X", i, a[i], b[i]);
            return false;
        }
    }
    return true;
}

// Helper to verify log entry integrity
static bool verify_log_entry(const uint8_t* expected_data, uint8_t expected_len, uint8_t expected_type) {
    uint8_t read_buf[LOG_MAX_PAYLOAD];
    uint8_t read_len;
    uint8_t read_type;
    
    esp_err_t err = log_read(&read_len, read_buf, &read_type);
    if (err == ESP_ERR_NOT_FOUND) {
        ESP_LOGE(TAG, "No more log entries to read (expected entry with length %d)", expected_len);
        return false;
    }
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read log entry: %s", esp_err_to_name(err));
        return false;
    }
    
    if (read_len != expected_len) {
        ESP_LOGE(TAG, "Length mismatch: expected %d, got %d", expected_len, read_len);
        return false;
    }
    
    if (read_type != expected_type) {
        ESP_LOGE(TAG, "Type mismatch: expected 0x%02X, got 0x%02X", expected_type, read_type);
        return false;
    }
    
    if (!arrays_equal(expected_data, read_buf, expected_len)) {
        return false;
    }
    
    return true;
}

// Test 1: Basic log integrity - write and read back entries
bool test_log_integrity_basic(void) {
    ESP_LOGI(TAG, "=== Test: Basic Log Integrity ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    // Erase already resets head/tail and reinitializes, no need for power cycle here
    
    const char* test_data1 = "Test Entry 1";
    const char* test_data2 = "Another test entry with more data";
    const char* test_data3 = "Short";
    
    if (log_write_blocking_test((const uint8_t*)test_data1, strlen(test_data1), LOG_TYPE_DATA) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to write entry 1");
        return false;
    }
    
    if (log_write_blocking_test((const uint8_t*)test_data2, strlen(test_data2), LOG_TYPE_EVENT) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to write entry 2");
        return false;
    }
    
    if (log_write_blocking_test((const uint8_t*)test_data3, strlen(test_data3), LOG_TYPE_DEBUG) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to write entry 3");
        return false;
    }
    
    wait_for_log_queue();
    log_read_reset();
    
    if (!verify_log_entry((const uint8_t*)test_data1, strlen(test_data1), LOG_TYPE_DATA)) {
        return false;
    }
    
    if (!verify_log_entry((const uint8_t*)test_data2, strlen(test_data2), LOG_TYPE_EVENT)) {
        return false;
    }
    
    if (!verify_log_entry((const uint8_t*)test_data3, strlen(test_data3), LOG_TYPE_DEBUG)) {
        return false;
    }
    
    ESP_LOGI(TAG, "Basic integrity test PASSED");
    return true;
}

// Test 2: Log integrity with wraparound
bool test_log_integrity_wraparound(void) {
    ESP_LOGI(TAG, "=== Test: Log Integrity with Wraparound ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint8_t test_pattern[64];
    for (int i = 0; i < 64; i++) {
        test_pattern[i] = i & 0xFF;
    }
    
    int entries_written = 0;
    for (int i = 0; i < 200; i++) {
        test_pattern[0] = i & 0xFF;
        if (log_write_blocking_test(test_pattern, 64, LOG_TYPE_DATA) == ESP_OK) {
            entries_written++;
        } else {
            ESP_LOGW(TAG, "Write failed at entry %d", i);
        }
        
        if (i % 20 == 0) {
            esp_task_wdt_reset();
        }
    }
    
    wait_for_log_queue();
    
    ESP_LOGI(TAG, "Wrote %d entries, reading back last few...", entries_written);
    
    log_read_reset();
    
    int entries_read = 0;
    uint8_t read_buf[LOG_MAX_PAYLOAD];
    uint8_t read_len, read_type;
    
    for (int i = 0; i < 10; i++) {
        if (log_read(&read_len, read_buf, &read_type) == ESP_OK) {
            entries_read++;
            if (read_len != 64) {
                ESP_LOGE(TAG, "Entry %d has wrong length: %d", i, read_len);
                return false;
            }
            if (read_type != LOG_TYPE_DATA) {
                ESP_LOGE(TAG, "Entry %d has wrong type: 0x%02X", i, read_type);
                return false;
            }
        } else {
            break;
        }
    }
    
    ESP_LOGI(TAG, "Successfully read %d entries after wraparound", entries_read);
    
    if (entries_read == 0) {
        ESP_LOGE(TAG, "Failed to read any entries after wraparound");
        return false;
    }
    
    ESP_LOGI(TAG, "Wraparound integrity test PASSED");
    return true;
}

// Test 3: Head/tail recovery after power cycle - empty log
bool test_log_head_tail_recovery_empty(void) {
    ESP_LOGI(TAG, "=== Test: Head/Tail Recovery - Empty Log ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint32_t head = log_get_head();
    uint32_t tail = log_get_tail();
    uint32_t log_start = log_get_offset();
    
    ESP_LOGI(TAG, "After power cycle: head=%lu, tail=%lu, log_start=%lu", 
             (unsigned long)head, (unsigned long)tail, (unsigned long)log_start);
    
    if (head != log_start || tail != log_start) {
        ESP_LOGE(TAG, "Empty log should have head and tail at start offset");
        return false;
    }
    
    ESP_LOGI(TAG, "Empty log recovery PASSED");
    return true;
}

// Test 4: Head/tail recovery - partial sector
bool test_log_head_tail_recovery_partial_sector(void) {
    ESP_LOGI(TAG, "=== Test: Head/Tail Recovery - Partial Sector ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint32_t head_before = log_get_head();
    
    const char* data1 = "Entry 1";
    const char* data2 = "Entry 2";
    const char* data3 = "Entry 3";
    
    log_write_blocking_test((const uint8_t*)data1, strlen(data1), LOG_TYPE_DATA);
    log_write_blocking_test((const uint8_t*)data2, strlen(data2), LOG_TYPE_DATA);
    log_write_blocking_test((const uint8_t*)data3, strlen(data3), LOG_TYPE_DATA);
    
    wait_for_log_queue();
    
    uint32_t head_after_writes = log_get_head();
    uint32_t tail_after_writes = log_get_tail();
    
    ESP_LOGI(TAG, "Before power cycle: head=%lu, tail=%lu", 
             (unsigned long)head_after_writes, (unsigned long)tail_after_writes);
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint32_t head_after_cycle = log_get_head();
    uint32_t tail_after_cycle = log_get_tail();
    
    ESP_LOGI(TAG, "After power cycle: head=%lu, tail=%lu", 
             (unsigned long)head_after_cycle, (unsigned long)tail_after_cycle);
    
    if (head_after_cycle < head_before || head_after_cycle > head_after_writes + 10) {
        ESP_LOGE(TAG, "Head not properly recovered: before=%lu, after=%lu", 
                 (unsigned long)head_after_writes, (unsigned long)head_after_cycle);
        return false;
    }
    
    log_read_reset();
    
    if (!verify_log_entry((const uint8_t*)data1, strlen(data1), LOG_TYPE_DATA)) {
        ESP_LOGE(TAG, "Failed to read entry 1 after recovery");
        return false;
    }
    
    if (!verify_log_entry((const uint8_t*)data2, strlen(data2), LOG_TYPE_DATA)) {
        ESP_LOGE(TAG, "Failed to read entry 2 after recovery");
        return false;
    }
    
    if (!verify_log_entry((const uint8_t*)data3, strlen(data3), LOG_TYPE_DATA)) {
        ESP_LOGE(TAG, "Failed to read entry 3 after recovery");
        return false;
    }
    
    ESP_LOGI(TAG, "Partial sector recovery PASSED");
    return true;
}

// Test 5: Head/tail recovery - multiple full sectors
bool test_log_head_tail_recovery_full_sectors(void) {
    ESP_LOGI(TAG, "=== Test: Head/Tail Recovery - Full Sectors ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint8_t pattern[100];
    for (int i = 0; i < 100; i++) {
        pattern[i] = i & 0xFF;
    }
    
    for (int i = 0; i < 100; i++) {
        pattern[0] = i & 0xFF;
        log_write_blocking_test(pattern, 100, LOG_TYPE_DATA);
        
        if (i % 20 == 0) {
            esp_task_wdt_reset();
        }
    }
    
    wait_for_log_queue();
    
    uint32_t head_before = log_get_head();
    uint32_t tail_before = log_get_tail();
    
    ESP_LOGI(TAG, "Before power cycle: head=%lu, tail=%lu", 
             (unsigned long)head_before, (unsigned long)tail_before);
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint32_t head_after = log_get_head();
    uint32_t tail_after = log_get_tail();
    
    ESP_LOGI(TAG, "After power cycle: head=%lu, tail=%lu", 
             (unsigned long)head_after, (unsigned long)tail_after);
    
    if (head_after < head_before - 1000 || head_after > head_before + 1000) {
        ESP_LOGE(TAG, "Head significantly changed after recovery");
        return false;
    }
    
    log_read_reset();
    
    uint8_t read_buf[LOG_MAX_PAYLOAD];
    uint8_t read_len, read_type;
    int entries_read = 0;
    
    for (int i = 0; i < 10; i++) {
        if (log_read(&read_len, read_buf, &read_type) == ESP_OK) {
            entries_read++;
        }
    }
    
    if (entries_read == 0) {
        ESP_LOGE(TAG, "Could not read any entries after recovery");
        return false;
    }
    
    ESP_LOGI(TAG, "Full sectors recovery PASSED (read %d entries)", entries_read);
    return true;
}

// Test 6: Head/tail recovery with wraparound
bool test_log_head_tail_recovery_wraparound(void) {
    ESP_LOGI(TAG, "=== Test: Head/Tail Recovery - Wraparound ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint8_t pattern[80];
    for (int i = 0; i < 80; i++) {
        pattern[i] = i & 0xFF;
    }
    
    for (int i = 0; i < 250; i++) {
        pattern[0] = i & 0xFF;
        log_write_blocking_test(pattern, 80, LOG_TYPE_DATA);
        
        if (i % 20 == 0) {
            esp_task_wdt_reset();
        }
    }
    
    wait_for_log_queue();
    
    uint32_t head_before = log_get_head();
    uint32_t tail_before = log_get_tail();
    
    ESP_LOGI(TAG, "Before power cycle (wraparound): head=%lu, tail=%lu", 
             (unsigned long)head_before, (unsigned long)tail_before);
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint32_t head_after = log_get_head();
    uint32_t tail_after = log_get_tail();
    
    ESP_LOGI(TAG, "After power cycle (wraparound): head=%lu, tail=%lu", 
             (unsigned long)head_after, (unsigned long)tail_after);
    
    log_read_reset();
    
    uint8_t read_buf[LOG_MAX_PAYLOAD];
    uint8_t read_len, read_type;
    int entries_read = 0;
    
    for (int i = 0; i < 10; i++) {
        if (log_read(&read_len, read_buf, &read_type) == ESP_OK) {
            entries_read++;
        }
    }
    
    if (entries_read == 0) {
        ESP_LOGE(TAG, "Could not read any entries after wraparound recovery");
        return false;
    }
    
    ESP_LOGI(TAG, "Wraparound recovery PASSED (read %d entries)", entries_read);
    return true;
}

// Test 7: Head equals tail (empty or full)
bool test_log_head_equals_tail(void) {
    ESP_LOGI(TAG, "=== Test: Head Equals Tail ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint32_t head = log_get_head();
    uint32_t tail = log_get_tail();
    
    if (head != tail) {
        ESP_LOGE(TAG, "Empty log should have head == tail");
        return false;
    }
    
    uint8_t read_buf[LOG_MAX_PAYLOAD];
    uint8_t read_len, read_type;
    
    esp_err_t err = log_read(&read_len, read_buf, &read_type);
    if (err == ESP_OK) {
        ESP_LOGW(TAG, "Read succeeded on empty log (head == tail), which may be okay");
    }
    
    ESP_LOGI(TAG, "Head equals tail test PASSED");
    return true;
}

// Test 8: Head = 0, Tail = 0
bool test_log_head_zero_tail_zero(void) {
    ESP_LOGI(TAG, "=== Test: Head=0, Tail=0 (actually LOG_START_OFFSET) ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint32_t head = log_get_head();
    uint32_t tail = log_get_tail();
    uint32_t log_start = log_get_offset();
    
    if (head != log_start || tail != log_start) {
        ESP_LOGE(TAG, "Fresh log should have both at LOG_START_OFFSET");
        return false;
    }
    
    const char* data = "First entry";
    log_write_blocking_test((const uint8_t*)data, strlen(data), LOG_TYPE_DATA);
    wait_for_log_queue();
    
    uint32_t head_after = log_get_head();
    uint32_t tail_after = log_get_tail();
    
    if (head_after == log_start) {
        ESP_LOGE(TAG, "Head should have advanced after write");
        return false;
    }
    
    if (tail_after != log_start) {
        ESP_LOGE(TAG, "Tail should still be at start");
        return false;
    }
    
    ESP_LOGI(TAG, "Head=0, Tail=0 test PASSED");
    return true;
}

// Test 9: Head > Tail (normal case)
bool test_log_head_greater_than_tail(void) {
    ESP_LOGI(TAG, "=== Test: Head > Tail (Normal Case) ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    for (int i = 0; i < 10; i++) {
        char data[32];
        snprintf(data, sizeof(data), "Entry %d", i);
        log_write_blocking_test((const uint8_t*)data, strlen(data), LOG_TYPE_DATA);
    }
    
    wait_for_log_queue();
    
    uint32_t head = log_get_head();
    uint32_t tail = log_get_tail();
    
    ESP_LOGI(TAG, "Head=%lu, Tail=%lu", (unsigned long)head, (unsigned long)tail);
    
    if (head <= tail && tail != log_get_offset()) {
        ESP_LOGE(TAG, "Expected head > tail in normal case");
        return false;
    }
    
    log_read_reset();
    
    uint8_t read_buf[LOG_MAX_PAYLOAD];
    uint8_t read_len, read_type;
    int entries_read = 0;
    
    for (int i = 0; i < 10; i++) {
        if (log_read(&read_len, read_buf, &read_type) == ESP_OK) {
            entries_read++;
        }
    }
    
    if (entries_read != 10) {
        ESP_LOGE(TAG, "Expected to read 10 entries, got %d", entries_read);
        return false;
    }
    
    ESP_LOGI(TAG, "Head > Tail test PASSED");
    return true;
}

// Test 10: Head < Tail (wraparound case)
bool test_log_head_less_than_tail(void) {
    ESP_LOGI(TAG, "=== Test: Head < Tail (Wraparound) ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint8_t pattern[90];
    for (int i = 0; i < 90; i++) {
        pattern[i] = i & 0xFF;
    }
    
    for (int i = 0; i < 300; i++) {
        pattern[0] = i & 0xFF;
        log_write_blocking_test(pattern, 90, LOG_TYPE_DATA);
        
        if (i % 20 == 0) {
            esp_task_wdt_reset();
        }
    }
    
    wait_for_log_queue();
    
    uint32_t head = log_get_head();
    uint32_t tail = log_get_tail();
    
    ESP_LOGI(TAG, "After wraparound: Head=%lu, Tail=%lu", 
             (unsigned long)head, (unsigned long)tail);
    
    if (tail < head && tail != log_get_offset()) {
        ESP_LOGW(TAG, "Expected wraparound condition, but may depend on partition size");
    }
    
    log_read_reset();
    
    uint8_t read_buf[LOG_MAX_PAYLOAD];
    uint8_t read_len, read_type;
    
    if (log_read(&read_len, read_buf, &read_type) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read after wraparound");
        return false;
    }
    
    ESP_LOGI(TAG, "Head < Tail test PASSED");
    return true;
}

// Test 11: Multiple wraparounds
bool test_log_wraparound_multiple_times(void) {
    ESP_LOGI(TAG, "=== Test: Multiple Wraparounds ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint8_t pattern[100];
    for (int i = 0; i < 100; i++) {
        pattern[i] = i & 0xFF;
    }
    
    int total_written = 0;
    for (int i = 0; i < 500; i++) {
        pattern[0] = i & 0xFF;
        if (log_write_blocking_test(pattern, 100, LOG_TYPE_DATA) == ESP_OK) {
            total_written++;
        }
        
        if (i % 20 == 0) {
            esp_task_wdt_reset();
        }
    }
    
    wait_for_log_queue();
    
    ESP_LOGI(TAG, "Wrote %d entries across multiple wraps", total_written);
    
    log_read_reset();
    
    uint8_t read_buf[LOG_MAX_PAYLOAD];
    uint8_t read_len, read_type;
    int entries_read = 0;
    
    for (int i = 0; i < 20; i++) {
        if (log_read(&read_len, read_buf, &read_type) == ESP_OK) {
            entries_read++;
        } else {
            break;
        }
    }
    
    ESP_LOGI(TAG, "Read %d entries after multiple wraps", entries_read);
    
    if (entries_read == 0) {
        ESP_LOGE(TAG, "Failed to read any entries after multiple wraps");
        return false;
    }
    
    ESP_LOGI(TAG, "Multiple wraparound test PASSED");
    return true;
}

// Test 12: Sector boundary conditions
bool test_log_sector_boundary_conditions(void) {
    ESP_LOGI(TAG, "=== Test: Sector Boundary Conditions ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint8_t pattern[100];
    for (int i = 0; i < 100; i++) {
        pattern[i] = i & 0xFF;
    }
    
    for (int i = 0; i < 50; i++) {
	    pattern[0] = i & 0xFF;
	    log_write_blocking_test(pattern, 100, LOG_TYPE_DATA);
	    
	    // Slow down to prevent queue overflow
	    if (i % 5 == 0) {
	        vTaskDelay(pdMS_TO_TICKS(50));
	    }
	    
	    if (i % 20 == 0) {
	        esp_task_wdt_reset();
	    }
	}
    
    wait_for_log_queue();
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    log_read_reset();
    
    uint8_t read_buf[LOG_MAX_PAYLOAD];
    uint8_t read_len, read_type;
    int entries_read = 0;
    
    for (int i = 0; i < 50; i++) {
        if (log_read(&read_len, read_buf, &read_type) == ESP_OK) {
            entries_read++;
            if (read_len != 100) {
                ESP_LOGE(TAG, "Entry %d has wrong length: %d", i, read_len);
                return false;
            }
        } else {
            break;
        }
    }
    
    if (entries_read != 50) {
        ESP_LOGE(TAG, "Expected 50 entries, read %d", entries_read);
        return false;
    }
    
    ESP_LOGI(TAG, "Sector boundary test PASSED");
    return true;
}

// Test 13: Maximum payload size
bool test_log_maximum_payload(void) {
    ESP_LOGI(TAG, "=== Test: Maximum Payload Size ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint8_t max_payload[LOG_MAX_PAYLOAD];
    for (int i = 0; i < LOG_MAX_PAYLOAD; i++) {
        max_payload[i] = i & 0xFF;
    }
    
    if (log_write_blocking_test(max_payload, LOG_MAX_PAYLOAD, LOG_TYPE_DATA) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to write maximum payload");
        return false;
    }
    
    wait_for_log_queue();
    log_read_reset();
    
    uint8_t read_buf[LOG_MAX_PAYLOAD];
    uint8_t read_len, read_type;
    
    if (log_read(&read_len, read_buf, &read_type) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read maximum payload");
        return false;
    }
    
    if (read_len != LOG_MAX_PAYLOAD) {
        ESP_LOGE(TAG, "Read length %d != expected %d", read_len, LOG_MAX_PAYLOAD);
        return false;
    }
    
    if (!arrays_equal(max_payload, read_buf, LOG_MAX_PAYLOAD)) {
        return false;
    }
    
    ESP_LOGI(TAG, "Maximum payload test PASSED");
    return true;
}

// Test 14: Minimum payload size (1 byte)
bool test_log_minimum_payload(void) {
    ESP_LOGI(TAG, "=== Test: Minimum Payload Size ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint8_t min_payload[1] = {0x42};
    
    if (log_write_blocking_test(min_payload, 1, LOG_TYPE_DEBUG) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to write minimum payload");
        return false;
    }
    
    wait_for_log_queue();
    log_read_reset();
    
    uint8_t read_buf[LOG_MAX_PAYLOAD];
    uint8_t read_len, read_type;
    
    if (log_read(&read_len, read_buf, &read_type) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read minimum payload");
        return false;
    }
    
    if (read_len != 1) {
        ESP_LOGE(TAG, "Read length %d != expected 1", read_len);
        return false;
    }
    
    if (read_buf[0] != 0x42) {
        ESP_LOGE(TAG, "Read data 0x%02X != expected 0x42", read_buf[0]);
        return false;
    }
    
    if (read_type != LOG_TYPE_DEBUG) {
        ESP_LOGE(TAG, "Read type 0x%02X != expected 0x%02X", read_type, LOG_TYPE_DEBUG);
        return false;
    }
    
    ESP_LOGI(TAG, "Minimum payload test PASSED");
    return true;
}

// Test 15: Corrupted entry recovery
bool test_log_corrupted_entry_recovery(void) {
    ESP_LOGI(TAG, "=== Test: Corrupted Entry Recovery ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    const char* data1 = "Good entry 1";
    const char* data2 = "Good entry 2";
    
    log_write_blocking_test((const uint8_t*)data1, strlen(data1), LOG_TYPE_DATA);
    log_write_blocking_test((const uint8_t*)data2, strlen(data2), LOG_TYPE_DATA);
    
    wait_for_log_queue();
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    log_read_reset();
    
    if (!verify_log_entry((const uint8_t*)data1, strlen(data1), LOG_TYPE_DATA)) {
        ESP_LOGE(TAG, "Failed to read entry 1 after simulated corruption test");
        return false;
    }
    
    if (!verify_log_entry((const uint8_t*)data2, strlen(data2), LOG_TYPE_DATA)) {
        ESP_LOGE(TAG, "Failed to read entry 2 after simulated corruption test");
        return false;
    }
    
    ESP_LOGI(TAG, "Corrupted entry recovery test PASSED (basic validation)");
    return true;
}

// Test 16: Full partition handling
bool test_log_full_partition(void) {
    ESP_LOGI(TAG, "=== Test: Full Partition Handling ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    uint8_t pattern[200];
    for (int i = 0; i < 200; i++) {
        pattern[i] = i & 0xFF;
    }
    
    int successful_writes = 0;
    for (int i = 0; i < 1000; i++) {
        pattern[0] = i & 0xFF;
        if (log_write_blocking_test(pattern, 200, LOG_TYPE_DATA) == ESP_OK) {
            successful_writes++;
        } else {
            ESP_LOGW(TAG, "Write failed at iteration %d", i);
        }
        
        if (i % 50 == 0) {
            vTaskDelay(pdMS_TO_TICKS(100));
            esp_task_wdt_reset();
        }
    }
    
    ESP_LOGI(TAG, "Successfully wrote %d entries before partition full", successful_writes);
    
    wait_for_log_queue();
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle on full partition");
        return false;
    }
    
    log_read_reset();
    
    uint8_t read_buf[LOG_MAX_PAYLOAD];
    uint8_t read_len, read_type;
    
    if (log_read(&read_len, read_buf, &read_type) != ESP_OK) {
        ESP_LOGE(TAG, "Failed to read from full partition");
        return false;
    }
    
    ESP_LOGI(TAG, "Full partition test PASSED");
    return true;
}

// Test 17: Read after write consistency
bool test_log_read_after_write(void) {
    ESP_LOGI(TAG, "=== Test: Read After Write Consistency ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    for (int i = 0; i < 20; i++) {
        char data[32];
        snprintf(data, sizeof(data), "Entry number %d", i);
        
        if (log_write_blocking_test((const uint8_t*)data, strlen(data), LOG_TYPE_DATA) != ESP_OK) {
            ESP_LOGE(TAG, "Failed to write entry %d", i);
            return false;
        }
    }
    
    wait_for_log_queue();
    log_read_reset();
    
    for (int i = 0; i < 20; i++) {
        char expected[32];
        snprintf(expected, sizeof(expected), "Entry number %d", i);
        
        if (!verify_log_entry((const uint8_t*)expected, strlen(expected), LOG_TYPE_DATA)) {
            ESP_LOGE(TAG, "Failed to verify entry %d", i);
            return false;
        }
    }
    
    ESP_LOGI(TAG, "Read after write consistency test PASSED");
    return true;
}

// Test 18: Multiple log types
bool test_log_multiple_types(void) {
    ESP_LOGI(TAG, "=== Test: Multiple Log Types ===");
    
    if (log_erase_all_sectors() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to erase log sectors");
        return false;
    }
    
    if (log_simulate_power_cycle() != ESP_OK) {
        ESP_LOGE(TAG, "Failed to simulate power cycle");
        return false;
    }
    
    const char* data_entry = "Data entry";
    const char* event_entry = "Event entry";
    const char* error_entry = "Error entry";
    const char* debug_entry = "Debug entry";
    const char* sensor_entry = "Sensor entry";
    
    log_write_blocking_test((const uint8_t*)data_entry, strlen(data_entry), LOG_TYPE_DATA);
    log_write_blocking_test((const uint8_t*)event_entry, strlen(event_entry), LOG_TYPE_EVENT);
    log_write_blocking_test((const uint8_t*)error_entry, strlen(error_entry), LOG_TYPE_ERROR);
    log_write_blocking_test((const uint8_t*)debug_entry, strlen(debug_entry), LOG_TYPE_DEBUG);
    log_write_blocking_test((const uint8_t*)sensor_entry, strlen(sensor_entry), LOG_TYPE_SENSOR);
    
    wait_for_log_queue();
    log_read_reset();
    
    if (!verify_log_entry((const uint8_t*)data_entry, strlen(data_entry), LOG_TYPE_DATA)) {
        return false;
    }
    
    if (!verify_log_entry((const uint8_t*)event_entry, strlen(event_entry), LOG_TYPE_EVENT)) {
        return false;
    }
    
    if (!verify_log_entry((const uint8_t*)error_entry, strlen(error_entry), LOG_TYPE_ERROR)) {
        return false;
    }
    
    if (!verify_log_entry((const uint8_t*)debug_entry, strlen(debug_entry), LOG_TYPE_DEBUG)) {
        return false;
    }
    
    if (!verify_log_entry((const uint8_t*)sensor_entry, strlen(sensor_entry), LOG_TYPE_SENSOR)) {
        return false;
    }
    
    ESP_LOGI(TAG, "Multiple log types test PASSED");
    return true;
}

// Helper function to print test results
void print_test_results(test_result_t* results, int num_tests) {
    ESP_LOGI(TAG, "\n\n");
    ESP_LOGI(TAG, "=================================================");
    ESP_LOGI(TAG, "TEST RESULTS SUMMARY");
    ESP_LOGI(TAG, "=================================================");
    
    int passed = 0;
    int failed = 0;
    
    ESP_LOGI(TAG, "\n--- FAILED TESTS ---");
    bool any_failures = false;
    for (int i = 0; i < num_tests; i++) {
        if (!results[i].passed) {
            ESP_LOGE(TAG, "[FAIL] Test %d: %s", i + 1, results[i].test_name);
            if (results[i].error_msg) {
                ESP_LOGE(TAG, "       Error: %s", results[i].error_msg);
            }
            failed++;
            any_failures = true;
        }
    }
    
    if (!any_failures) {
        ESP_LOGI(TAG, "None - all tests passed!");
    }
    
    ESP_LOGI(TAG, "\n--- PASSED TESTS ---");
    for (int i = 0; i < num_tests; i++) {
        if (results[i].passed) {
            ESP_LOGI(TAG, "[PASS] Test %d: %s", i + 1, results[i].test_name);
            passed++;
        }
    }
    
    ESP_LOGI(TAG, "\n=================================================");
    ESP_LOGI(TAG, "Total: %d | Passed: %d | Failed: %d", num_tests, passed, failed);
    if (failed > 0) {
        ESP_LOGE(TAG, "FAILED TESTS: %d", failed);
    } else {
        ESP_LOGI(TAG, "ALL TESTS PASSED!");
    }
    ESP_LOGI(TAG, "=================================================\n");
}

int count_passed_tests(test_result_t* results, int num_tests) {
    int passed = 0;
    for (int i = 0; i < num_tests; i++) {
        if (results[i].passed) {
            passed++;
        }
    }
    return passed;
}

// Main test runner
esp_err_t run_all_log_tests(void) {
    ESP_LOGI(TAG, "\n\n");
    ESP_LOGI(TAG, "=================================================");
    ESP_LOGI(TAG, "STARTING COMPREHENSIVE LOG TESTS");
    ESP_LOGI(TAG, "=================================================\n");
    
    if (storage_init() != ESP_OK) {
        ESP_LOGE(TAG, "STORAGE FAILED");
        return ESP_FAIL;
    }
    
    ESP_LOGI(TAG, "Storage initialized successfully");
    
    typedef struct {
        const char* name;
        bool (*test_func)(void);
    } test_entry_t;
    
    test_entry_t tests[] = {
        {"Basic Log Integrity", test_log_integrity_basic},
        {"Log Integrity with Wraparound", test_log_integrity_wraparound},
        {"Head/Tail Recovery - Empty Log", test_log_head_tail_recovery_empty},
        {"Head/Tail Recovery - Partial Sector", test_log_head_tail_recovery_partial_sector},
        {"Head/Tail Recovery - Full Sectors", test_log_head_tail_recovery_full_sectors},
        {"Head/Tail Recovery - Wraparound", test_log_head_tail_recovery_wraparound},
        {"Head Equals Tail", test_log_head_equals_tail},
        {"Head=0, Tail=0", test_log_head_zero_tail_zero},
        {"Head > Tail (Normal)", test_log_head_greater_than_tail},
        {"Head < Tail (Wraparound)", test_log_head_less_than_tail},
        {"Multiple Wraparounds", test_log_wraparound_multiple_times},
        {"Sector Boundary Conditions", test_log_sector_boundary_conditions},
        {"Maximum Payload Size", test_log_maximum_payload},
        {"Minimum Payload Size", test_log_minimum_payload},
        {"Corrupted Entry Recovery", test_log_corrupted_entry_recovery},
        {"Full Partition Handling", test_log_full_partition},
        {"Read After Write Consistency", test_log_read_after_write},
        {"Multiple Log Types", test_log_multiple_types},
    };
    
    int num_tests = sizeof(tests) / sizeof(tests[0]);
    test_result_t* results = malloc(num_tests * sizeof(test_result_t));
    
    if (results == NULL) {
        ESP_LOGE(TAG, "Failed to allocate memory for test results");
        return ESP_ERR_NO_MEM;
    }
    
    for (int i = 0; i < num_tests; i++) {
        ESP_LOGI(TAG, "\n--- Running Test %d/%d: %s ---", i + 1, num_tests, tests[i].name);
        
        esp_task_wdt_reset();
        
        results[i].test_name = tests[i].name;
        results[i].passed = tests[i].test_func();
        results[i].error_msg = NULL;
        
        if (results[i].passed) {
            ESP_LOGI(TAG, ">>> TEST PASSED: %s <<<", tests[i].name);
        } else {
            ESP_LOGE(TAG, ">>> TEST FAILED: %s <<<", tests[i].name);
            ESP_LOGE(TAG, ">>> STOPPING AT FIRST FAILURE <<<");
            
            for (int j = i + 1; j < num_tests; j++) {
                results[j].test_name = tests[j].name;
                results[j].passed = false;
                results[j].error_msg = "Not run - stopped at first failure";
            }
            break;
        }
        
        esp_task_wdt_reset();
        vTaskDelay(pdMS_TO_TICKS(100));
    }
    
    print_test_results(results, num_tests);
    
    int passed = count_passed_tests(results, num_tests);
    free(results);
    
    if (passed == num_tests) {
        ESP_LOGI(TAG, "ALL TESTS PASSED!");
        
    } else {
        ESP_LOGE(TAG, "SOME TESTS FAILED!");

    }
    
    while(1) { esp_task_wdt_reset(); vTaskDelay(pdMS_TO_TICKS(100)); }
    return ESP_OK;
}