/**
 * ESP32-P4-NANO Network Auditing Multi-Tool
 * Main firmware entry point with dual-core architecture
 * 
 * Core 0 (ESP32-P4): Ethernet network operations, scanning, monitoring
 * Core 1 (ESP32-C6): Wi-Fi Access Point, web server, user interface
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/event_groups.h>
#include <freertos/semphr.h>
#include <esp_system.h>
#include <esp_log.h>
#include <esp_err.h>
#include <esp_event.h>
#include <nvs_flash.h>
#include <driver/gpio.h>
#include <esp_timer.h>

// Network interface headers
#include <esp_netif.h>
#include <esp_eth.h>
#include <esp_wifi.h>

// SD card and file system
#include <esp_vfs_fat.h>
#include <sdmmc_cmd.h>

// HTTP server
#include <esp_http_server.h>

// Custom component headers
#include "network_manager.h"
#include "web_server.h"
#include "sd_manager.h"
#include "scanner_engine.h"
#include "security_manager.h"
#include "led_manager.h"
#include "ota_manager.h"
#include "config_manager.h"
#include "log_manager.h"

static const char *TAG = "MAIN";

// System status and synchronization
static EventGroupHandle_t system_events;

// Event bits for system coordination
#define SYSTEM_INIT_BIT         BIT0
#define ETHERNET_READY_BIT      BIT1
#define WIFI_AP_READY_BIT       BIT2
#define SD_CARD_READY_BIT       BIT3
#define WEB_SERVER_READY_BIT    BIT4
#define SCANNER_READY_BIT       BIT5

// Status LED GPIO (customize based on your board)
#define STATUS_LED_GPIO         GPIO_NUM_2
#define ERROR_LED_GPIO          GPIO_NUM_4

// Debug configuration
static bool s_debug_enabled = false;
static bool s_debug_matrix_enabled = false;

/**
 * Enable comprehensive debugging based on web research best practices
 */
static void enable_debugging(void) {
    // Enable debug output for all components
    s_debug_enabled = true;
    s_debug_matrix_enabled = true;
    
    // Configure network manager debugging
    network_manager_set_debug(true);
    network_manager_set_matrix_debug(true);
    
    ESP_LOGI(TAG, "Comprehensive debugging enabled");
    ESP_LOGI(TAG, "Debug features: network events, matrix scanning, error tracking");
}

/**
 * Initialize system components with enhanced error handling
 */
static esp_err_t initialize_system_components(void) {
    esp_err_t ret = ESP_OK;
    
    ESP_LOGI(TAG, "Initializing system components with enhanced debugging");
    
    // Initialize NVS
    ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);
    ESP_LOGI(TAG, "NVS initialized successfully");
    
    // Initialize event loop
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    ESP_LOGI(TAG, "Event loop created successfully");
    
    // Initialize SD card manager
    ret = sd_manager_init();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize SD card manager: %s", esp_err_to_name(ret));
        return ret;
    }
    ESP_LOGI(TAG, "SD card manager initialized successfully");
    xEventGroupSetBits(system_events, SD_CARD_READY_BIT);
    
    // Initialize log manager
    ret = log_manager_init();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize log manager: %s", esp_err_to_name(ret));
        return ret;
    }
    ESP_LOGI(TAG, "Log manager initialized successfully");
    
    // Initialize configuration manager
    ret = config_manager_init();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize config manager: %s", esp_err_to_name(ret));
        return ret;
    }
    ESP_LOGI(TAG, "Configuration manager initialized successfully");
    
    // Initialize LED manager
    ret = led_manager_init();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize LED manager: %s", esp_err_to_name(ret));
        return ret;
    }
    ESP_LOGI(TAG, "LED manager initialized successfully");
    
    // Initialize security manager
    ret = security_manager_init();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize security manager: %s", esp_err_to_name(ret));
        return ret;
    }
    ESP_LOGI(TAG, "Security manager initialized successfully");
    
    // Initialize scanner engine
    ret = scanner_engine_init();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize scanner engine: %s", esp_err_to_name(ret));
        return ret;
    }
    ESP_LOGI(TAG, "Scanner engine initialized successfully");
    
    // Initialize network interfaces
    ret = network_manager_init_ethernet();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize Ethernet: %s", esp_err_to_name(ret));
        return ret;
    }
    ESP_LOGI(TAG, "Ethernet interface initialized successfully");
    xEventGroupSetBits(system_events, ETHERNET_READY_BIT);
    
    ret = network_manager_init_wifi_ap();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize WiFi AP: %s", esp_err_to_name(ret));
        return ret;
    }
    ESP_LOGI(TAG, "WiFi AP interface initialized successfully");
    xEventGroupSetBits(system_events, WIFI_AP_READY_BIT);
    
    // Initialize web server
    ret = web_server_init();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize web server: %s", esp_err_to_name(ret));
        return ret;
    }
    ESP_LOGI(TAG, "Web server initialized successfully");
    xEventGroupSetBits(system_events, WEB_SERVER_READY_BIT);
    
    // Initialize OTA manager
    ret = ota_manager_init();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to initialize OTA manager: %s", esp_err_to_name(ret));
        return ret;
    }
    ESP_LOGI(TAG, "OTA manager initialized successfully");
    
    ESP_LOGI(TAG, "All system components initialized successfully");
    return ESP_OK;
}

/**
 * System monitoring task with enhanced debugging
 */
static void system_monitor_task(void *pvParameters) {
    ESP_LOGI(TAG, "System monitor task started");
    
    while (1) {
        // Update network statistics
        network_manager_update_stats();
        
        // Monitor system health
        network_stats_t eth_stats, wifi_stats;
        if (network_manager_get_stats(NETIF_TYPE_ETHERNET, &eth_stats) == ESP_OK) {
            if (s_debug_enabled) {
                ESP_LOGD(TAG, "Ethernet: link=%s, rx_pkts=%lu, tx_pkts=%lu", 
                         eth_stats.link_up ? "UP" : "DOWN", 
                         eth_stats.rx_packets, eth_stats.tx_packets);
            }
        }
        
        if (network_manager_get_stats(NETIF_TYPE_WIFI_AP, &wifi_stats) == ESP_OK) {
            if (s_debug_enabled) {
                ESP_LOGD(TAG, "WiFi AP: link=%s, rx_pkts=%lu, tx_pkts=%lu", 
                         wifi_stats.link_up ? "UP" : "DOWN", 
                         wifi_stats.rx_packets, wifi_stats.tx_packets);
            }
        }
        
        // Rotate logs periodically
        log_manager_rotate_logs();
        
        // Update LED status based on system state
        led_manager_set_status(LED_STATUS_SYSTEM_ERROR);
        
        vTaskDelay(pdMS_TO_TICKS(5000)); // 5 second interval
    }
}

/**
 * Debug information task
 */
static void debug_info_task(void *pvParameters) {
    ESP_LOGI(TAG, "Debug info task started");
    
    while (1) {
        if (s_debug_enabled) {
            // Print system information
            ESP_LOGI(TAG, "=== System Debug Information ===");
            ESP_LOGI(TAG, "Free heap: %lu bytes", esp_get_free_heap_size());
            ESP_LOGI(TAG, "Minimum free heap: %lu bytes", esp_get_minimum_free_heap_size());
            ESP_LOGI(TAG, "Uptime: %lld seconds", esp_timer_get_time() / 1000000);
            
            // Print network status
            network_stats_t eth_stats, wifi_stats;
            if (network_manager_get_stats(NETIF_TYPE_ETHERNET, &eth_stats) == ESP_OK) {
                ESP_LOGI(TAG, "Ethernet: link=%s, rx_pkts=%lu, tx_pkts=%lu, rx_err=%lu, tx_err=%lu", 
                         eth_stats.link_up ? "UP" : "DOWN", 
                         eth_stats.rx_packets, eth_stats.tx_packets,
                         eth_stats.rx_errors, eth_stats.tx_errors);
            }
            
            if (network_manager_get_stats(NETIF_TYPE_WIFI_AP, &wifi_stats) == ESP_OK) {
                ESP_LOGI(TAG, "WiFi AP: link=%s, rx_pkts=%lu, tx_pkts=%lu, rx_err=%lu, tx_err=%lu", 
                         wifi_stats.link_up ? "UP" : "DOWN", 
                         wifi_stats.rx_packets, wifi_stats.tx_packets,
                         wifi_stats.rx_errors, wifi_stats.tx_errors);
            }
            
            ESP_LOGI(TAG, "=== End Debug Information ===");
        }
        
        vTaskDelay(pdMS_TO_TICKS(30000)); // 30 second interval
    }
}

/**
 * ============================================================================
 * CORE 0 TASK: ETHERNET NETWORK OPERATIONS
 * ============================================================================
 * 
 * Handles all target network interactions:
 * - Ethernet interface management (LAN8720 RMII PHY)
 * - Network scanning (ARP, port, ICMP)
 * - Passive monitoring (DNS, DHCP)
 * - Packet injection and analysis
 * - Real-time network reconnaissance
 * 
 * This task runs on ESP32-P4 core and is isolated from Wi-Fi operations
 * to maintain air-gapped network segmentation.
 */
void ethernet_core_task(void *pvParameters) {
    ESP_LOGI(TAG, "Starting Ethernet Core Task on Core %d", xPortGetCoreID());
    
    // Wait for system initialization
    xEventGroupWaitBits(system_events, SYSTEM_INIT_BIT, false, true, portMAX_DELAY);
    
    // Initialize Ethernet interface
    esp_err_t ret = network_manager_init_ethernet();
    if (ret == ESP_OK) {
        xEventGroupSetBits(system_events, ETHERNET_READY_BIT);
        ESP_LOGI(TAG, "Ethernet interface initialized successfully");
        
        // Initialize network scanner engine
        ret = scanner_engine_init();
        if (ret == ESP_OK) {
            xEventGroupSetBits(system_events, SCANNER_READY_BIT);
            ESP_LOGI(TAG, "Scanner engine initialized successfully");
        } else {
            ESP_LOGE(TAG, "Failed to initialize scanner engine: %s", esp_err_to_name(ret));
        }
    } else {
        ESP_LOGE(TAG, "Failed to initialize Ethernet interface: %s", esp_err_to_name(ret));
    }
    
    // Main ethernet core loop
    while (1) {
        // Monitor network status
        network_manager_monitor_ethernet();
        
        // Process pending scan requests
        scanner_engine_process_queue();
        
        // Update network statistics
        network_manager_update_stats();
        
        vTaskDelay(pdMS_TO_TICKS(100)); // 100ms cycle
    }
}

/**
 * ============================================================================
 * CORE 1 TASK: WI-FI ACCESS POINT AND WEB INTERFACE
 * ============================================================================
 * 
 * Handles operator interface:
 * - Wi-Fi Access Point (ESP32-C6) - isolated from Ethernet
 * - HTTP web server with REST API
 * - File serving from SD card (FAT32)
 * - User authentication and security
 * - Real-time status updates
 * 
 * This task runs on ESP32-C6 core and provides the operator interface
 * while maintaining complete network segmentation from target network.
 */
void wifi_core_task(void *pvParameters) {
    ESP_LOGI(TAG, "Starting Wi-Fi Core Task on Core %d", xPortGetCoreID());
    
    // Wait for system initialization and SD card
    EventBits_t bits = xEventGroupWaitBits(system_events, 
                                          SYSTEM_INIT_BIT | SD_CARD_READY_BIT, 
                                          false, true, portMAX_DELAY);
    
    if (bits & (SYSTEM_INIT_BIT | SD_CARD_READY_BIT)) {
        // Initialize Wi-Fi Access Point
        esp_err_t ret = network_manager_init_wifi_ap();
        if (ret == ESP_OK) {
            xEventGroupSetBits(system_events, WIFI_AP_READY_BIT);
            ESP_LOGI(TAG, "Wi-Fi Access Point initialized successfully");
            
            // Initialize web server
            ret = web_server_init();
            if (ret == ESP_OK) {
                xEventGroupSetBits(system_events, WEB_SERVER_READY_BIT);
                ESP_LOGI(TAG, "Web server initialized successfully");
            } else {
                ESP_LOGE(TAG, "Failed to initialize web server: %s", esp_err_to_name(ret));
            }
        } else {
            ESP_LOGE(TAG, "Failed to initialize Wi-Fi AP: %s", esp_err_to_name(ret));
        }
    }
    
    // Main wifi core loop
    while (1) {
        // Monitor Wi-Fi status
        network_manager_monitor_wifi();
        
        // Process web server requests (handled by HTTP server callbacks)
        
        // Update system status
        web_server_update_status();
        
        vTaskDelay(pdMS_TO_TICKS(1000)); // 1 second cycle
    }
}

/**
 * ============================================================================
 * STATUS LED MANAGEMENT TASK
 * ============================================================================
 * 
 * Provides visual feedback for system status:
 * - Solid green: System fully operational
 * - Blinking green: System initializing
 * - Blinking red: Error state
 * 
 * Uses GPIO pins for status indication on ESP32-P4-NANO board.
 */
void status_led_task(void *pvParameters) {
    gpio_config_t io_conf{}; // zero-initialize
    io_conf.pin_bit_mask = (1ULL << STATUS_LED_GPIO) | (1ULL << ERROR_LED_GPIO);
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    gpio_config(&io_conf);
    
    while (1) {
        EventBits_t bits = xEventGroupGetBits(system_events);
        
        if (bits & WEB_SERVER_READY_BIT && bits & ETHERNET_READY_BIT) {
            // System fully operational - solid green
            gpio_set_level(STATUS_LED_GPIO, 1);
            gpio_set_level(ERROR_LED_GPIO, 0);
            vTaskDelay(pdMS_TO_TICKS(1000));
        } else if (bits & SYSTEM_INIT_BIT) {
            // System initializing - blinking green
            gpio_set_level(STATUS_LED_GPIO, 1);
            vTaskDelay(pdMS_TO_TICKS(250));
            gpio_set_level(STATUS_LED_GPIO, 0);
            vTaskDelay(pdMS_TO_TICKS(250));
        } else {
            // Error state - blinking red
            gpio_set_level(ERROR_LED_GPIO, 1);
            vTaskDelay(pdMS_TO_TICKS(500));
            gpio_set_level(ERROR_LED_GPIO, 0);
            vTaskDelay(pdMS_TO_TICKS(500));
        }
    }
}

/**
 * ============================================================================
 * MAIN APPLICATION ENTRY POINT
 * ============================================================================
 * 
 * Initializes the ESP32-P4-NANO network auditing multi-tool:
 * - System initialization (NVS, network stack, event loop)
 * - Component initialization (security, LED, OTA, config, log managers)
 * - SD card initialization for file storage
 * - Dual-core task creation with CPU affinity
 * - Event group synchronization setup
 * 
 * Creates air-gapped dual-interface architecture:
 * - Core 0: Ethernet operations (target network)
 * - Core 1: Wi-Fi AP operations (operator interface)
 */
extern "C" void app_main(void) {
    ESP_LOGI(TAG, "ESP32-P4 Network Auditing Tool Starting...");
    ESP_LOGI(TAG, "Version: 1.0.0");
    ESP_LOGI(TAG, "Build Date: %s %s", __DATE__, __TIME__);
    
    // Create system event group
    system_events = xEventGroupCreate();
    if (system_events == NULL) {
        ESP_LOGE(TAG, "Failed to create system event group");
        return;
    }
    
    // Enable comprehensive debugging
    enable_debugging();
    
    // Initialize system components
    esp_err_t ret = initialize_system_components();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "System initialization failed: %s", esp_err_to_name(ret));
        return;
    }
    
    // Create system monitoring task
    xTaskCreate(system_monitor_task, "system_monitor", 4096, NULL, 5, NULL);
    
    // Create debug information task
    xTaskCreate(debug_info_task, "debug_info", 4096, NULL, 3, NULL);
    
    ESP_LOGI(TAG, "ESP32-P4 Network Auditing Tool started successfully");
    ESP_LOGI(TAG, "System ready for network auditing operations");
    
    // Main application loop
    while (1) {
        // Check system status
        EventBits_t bits = xEventGroupGetBits(system_events);
        
        if (bits & ETHERNET_READY_BIT) {
            ESP_LOGD(TAG, "Ethernet interface ready");
        }
        
        if (bits & WIFI_AP_READY_BIT) {
            ESP_LOGD(TAG, "WiFi AP interface ready");
        }
        
        if (bits & SD_CARD_READY_BIT) {
            ESP_LOGD(TAG, "SD card ready");
        }
        
        if (bits & WEB_SERVER_READY_BIT) {
            ESP_LOGD(TAG, "Web server ready");
        }
        
        vTaskDelay(pdMS_TO_TICKS(10000)); // 10 second interval
    }
}
