/**
 * Scanner Engine - Network Reconnaissance and Analysis
 * Provides ARP, port scanning, DNS monitoring, and packet analysis
 */

#ifndef SCANNER_ENGINE_H
#define SCANNER_ENGINE_H

#include <esp_err.h>
#include <esp_system.h>
#include <lwip/ip_addr.h>
#include <lwip/ip4_addr.h>
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
#include <stdint.h>
#include <stdbool.h>

// Constants
#define MAX_DEVICES 100
#define MAX_MAC_VENDORS 1000
#define DNS_MAX_NAME_LEN 256

// MAC vendor database entry
typedef struct {
    uint8_t prefix[3];
    char vendor[64];
} mac_vendor_entry_t;

#ifdef __cplusplus
extern "C" {
#endif

// Scan types
typedef enum {
    SCAN_TYPE_ARP = 0,
    SCAN_TYPE_PORT_TCP,
    SCAN_TYPE_PORT_SYN,
    SCAN_TYPE_ICMP_PING,
    SCAN_TYPE_DNS_MONITOR,
    SCAN_TYPE_DHCP_MONITOR,
    SCAN_TYPE_PASSIVE_SNIFF,
    SCAN_TYPE_MAX
} scan_type_t;

// Scan status
typedef enum {
    SCAN_STATUS_IDLE = 0,
    SCAN_STATUS_RUNNING,
    SCAN_STATUS_COMPLETED,
    SCAN_STATUS_ERROR,
    SCAN_STATUS_CANCELLED
} scan_status_t;

// Port scan methods
typedef enum {
    PORT_SCAN_TCP_CONNECT = 0,
    PORT_SCAN_TCP_SYN,
    PORT_SCAN_UDP
} port_scan_method_t;

// Discovered device structure
typedef struct {
    ip4_addr_t ip_addr;
    uint8_t mac_addr[6];
    char hostname[64];
    char vendor[32];
    uint32_t response_time;
    uint16_t open_ports[256];
    uint8_t open_port_count;
    uint32_t last_seen;
    bool is_active;
} discovered_device_t;

// Scan configuration
typedef struct {
    scan_type_t type;
    ip4_addr_t start_ip;
    ip4_addr_t end_ip;
    uint16_t port_start;
    uint16_t port_end;
    port_scan_method_t method;
    uint32_t timeout_ms;
    uint32_t delay_ms;
    bool aggressive_mode;
    char output_file[128];
} scan_config_t;

// Scan request structure
typedef struct {
    uint32_t scan_id;
    scan_config_t config;
    scan_status_t status;
    uint32_t progress_percent;
    uint32_t devices_found;
    uint32_t start_time;
    uint32_t end_time;
    char error_message[256];
} scan_request_t;

// Scanner statistics
typedef struct {
    uint32_t total_scans;
    uint32_t successful_scans;
    uint32_t failed_scans;
    uint32_t devices_discovered;
    uint32_t ports_scanned;
    uint32_t packets_sent;
    uint32_t packets_received;
    uint32_t scan_time_ms;
} scanner_stats_t;

// DNS monitoring structures
typedef struct {
    char domain[256];
    char query_type[8];
    char source_ip[16];
    uint32_t timestamp;
} dns_query_t;

// DHCP monitoring structures
typedef struct {
    uint8_t mac_addr[6];
    ip4_addr_t ip_addr;
    uint32_t lease_time;
    uint32_t timestamp;
    char hostname[64];
    char message_type[16];
} dhcp_lease_t;

// Packet capture configuration
typedef struct {
    int interface_index;
    bool promiscuous;
    bool save_pcap;
    const char *filter;
} capture_config_t;

// Packet information
typedef struct {
    uint32_t timestamp;
    uint16_t protocol;
    char source[32];
    char destination[32];
    uint16_t source_port;
    uint16_t destination_port;
    uint32_t length;
    char info[256];
    uint8_t *payload;
    uint32_t payload_length;
} packet_info_t;

#define MAX_CONCURRENT_SCANS    3
#define MAX_DISCOVERED_DEVICES  1000
#define SCAN_QUEUE_SIZE         10
#define DEFAULT_PORT_TIMEOUT    1000  // 1 second
#define DEFAULT_SCAN_DELAY      10    // 10ms between requests

/**
 * Initialize scanner engine
 * @return ESP_OK on success, error code otherwise
 */
esp_err_t scanner_engine_init(void);

/**
 * Deinitialize scanner engine
 * @return ESP_OK on success
 */
esp_err_t scanner_engine_deinit(void);

/**
 * Start network scan
 * @param config Scan configuration
 * @param scan_id Pointer to store scan ID
 * @return ESP_OK on success
 */
esp_err_t scanner_engine_start_scan(const scan_config_t *config, uint32_t *scan_id);

/**
 * Stop active scan
 * @param scan_id Scan ID to stop
 * @return ESP_OK on success
 */
esp_err_t scanner_engine_stop_scan(uint32_t scan_id);

/**
 * Get scan results
 * @param devices Buffer to store discovered devices
 * @param count On input: buffer size, on output: actual device count
 * @return ESP_OK on success
 */
esp_err_t scanner_engine_get_results(discovered_device_t *devices, size_t *count);

/**
 * Get scan status
 * @param scan_id Scan ID
 * @param status Buffer to store scan status
 * @return ESP_OK on success
 */
esp_err_t scanner_engine_get_scan_status(uint32_t scan_id, scan_request_t *status);

/**
 * Process scan queue (legacy function for compatibility)
 */
void scanner_engine_process_queue(void);

/**
 * Get discovered devices
 * @param devices Array to store devices
 * @param max_devices Maximum number of devices to return
 * @param device_count Pointer to store actual device count
 * @return ESP_OK on success
 */
esp_err_t scanner_engine_get_devices(discovered_device_t *devices, size_t max_devices, size_t *device_count);

/**
 * Clear discovered devices list
 * @return ESP_OK on success
 */
esp_err_t scanner_engine_clear_devices(void);

/**
 * Get scanner statistics
 * @param stats Pointer to store statistics
 * @return ESP_OK on success
 */
esp_err_t scanner_engine_get_stats(scanner_stats_t *stats);

/**
 * Reset scanner statistics
 * @return ESP_OK on success
 */
esp_err_t scanner_engine_reset_stats(void);

/**
 * Export scan results to file
 * @param scan_id Scan ID
 * @param format Export format ("json", "csv", "xml")
 * @param filepath Output file path
 * @return ESP_OK on success
 */
esp_err_t scanner_engine_export_results(uint32_t scan_id, const char *format, const char *filepath);

// Specific scan functions
/**
 * Perform ARP scan
 * @param config Scan configuration
 * @return ESP_OK on success
 */
esp_err_t scanner_arp_scan(const scan_config_t *config);

/**
 * Perform TCP port scan
 * @param config Scan configuration
 * @return ESP_OK on success
 */
esp_err_t scanner_tcp_port_scan(const scan_config_t *config);

/**
 * Perform ICMP ping sweep
 * @param config Scan configuration
 * @return ESP_OK on success
 */
esp_err_t scanner_icmp_ping_sweep(const scan_config_t *config);

/**
 * Start DNS monitoring
 * @param duration_seconds Duration to monitor (0 = continuous)
 * @return ESP_OK on success
 */
esp_err_t scanner_start_dns_monitor(uint32_t duration_seconds);

/**
 * Stop DNS monitoring
 * @return ESP_OK on success
 */
esp_err_t scanner_stop_dns_monitor(void);

/**
 * Get DNS queries from monitor
 * @param queries Array to store queries
 * @param max_queries Maximum number of queries to retrieve
 * @param query_count Actual number of queries retrieved
 * @return ESP_OK on success
 */
esp_err_t scanner_get_dns_queries(dns_query_t *queries, size_t max_queries, size_t *query_count);

/**
 * Start DHCP monitoring
 * @param duration_seconds Duration to monitor (0 = continuous)
 * @return ESP_OK on success
 */
esp_err_t scanner_start_dhcp_monitor(uint32_t duration_seconds);

/**
 * Stop DHCP monitoring
 * @return ESP_OK on success
 */
esp_err_t scanner_stop_dhcp_monitor(void);

/**
 * Get DHCP leases from monitor
 * @param leases Array to store leases
 * @param max_leases Maximum number of leases to retrieve
 * @param lease_count Actual number of leases retrieved
 * @return ESP_OK on success
 */
esp_err_t scanner_get_dhcp_leases(dhcp_lease_t *leases, size_t max_leases, size_t *lease_count);

/**
 * Start passive network sniffing
 * @param duration_seconds Duration to sniff (0 = continuous)
 * @param pcap_file PCAP file to save packets (optional)
 * @return ESP_OK on success
 */
esp_err_t scanner_start_passive_sniff(uint32_t duration_seconds, const char *pcap_file);

/**
 * Stop passive packet sniffing
 * @return ESP_OK on success
 */
esp_err_t scanner_stop_passive_sniff(void);

/**
 * Get current PCAP file path
 * @param filename Buffer to store filename
 * @param size Buffer size
 * @return ESP_OK on success
 */
esp_err_t scanner_get_pcap_file(char *filename, size_t size);

// MAC vendor database functions
esp_err_t load_mac_vendor_database(void);

#ifdef __cplusplus
}
#endif

#endif // SCANNER_ENGINE_H 