//! Website server implementation
//!
//! This crate provides the Axum-based server for the website, integrating
//! with Rustelo's SSR capabilities and custom routing system.
#![recursion_limit = "512"]
#![allow(unused_variables, dead_code)]

#[cfg(feature = "wasm-client")]
pub mod app;
pub mod htmx_env;
pub mod htmx_grid;
pub mod htmx_pages;
pub mod resources;
pub mod run;
#[cfg(feature = "wasm-client")]
pub mod server_fn_register;
pub mod shell;
pub mod theme;

use axum::{http::StatusCode, response::Html, Json};
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use std::sync::{Arc, Mutex};

// Note: AppComponent will be provided by the shell component

// Top-level generated includes: server_config.rs + server_routing.rs (core, no Leptos deps)
include!(concat!(env!("OUT_DIR"), "/server_top_includes.rs"));
// Leptos page dispatch — only available when website-pages / wasm-client is active
#[cfg(feature = "wasm-client")]
include!(concat!(env!("OUT_DIR"), "/server_routing_leptos.rs"));

/// Resolves a URL path to the base component name (without "Page" suffix).
/// Wraps the private generated `get_component_for_path` so it's accessible
/// from child modules (e.g., `shell.rs`).
pub(crate) fn resolve_component_for_path(path: &str) -> &'static str {
    get_component_for_path(path)
}

pub mod generated {
    // generated_routes.rs: RouteComponent enum from site/config/index.ncl
    include!(concat!(env!("OUT_DIR"), "/server_generated_mod_includes.rs"));
}

pub mod config_constants {
    // config_constants.rs (env-var helpers) + ncl_database_constants.rs + ncl_path_constants.rs
    include!(concat!(env!("OUT_DIR"), "/server_config_mod_includes.rs"));
}

// TODO: Re-enable when content types are properly configured
// pub mod content_kinds {
//     include!(concat!(env!("OUT_DIR"), "/content_kinds_generated.rs"));
// }

// Legacy: Old resource_registry module (disabled - now using resources.rs module)
// pub mod resources {
//     include!(concat!(env!("OUT_DIR"), "/resource_registry.rs"));
// }

/// Log entry structure for browser console capture
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogEntry {
    pub timestamp: String,
    pub level: String,
    pub message: String,
    #[serde(skip)]
    pub args: Vec<String>,
}

/// Request structure for log endpoint
#[derive(Debug, Deserialize)]
pub struct LogRequest {
    pub logs: Vec<LogEntry>,
}

lazy_static! {
    /// Global log storage (in-memory for now)
    pub static ref LOG_STORE: Arc<Mutex<Vec<LogEntry>>> = Arc::new(Mutex::new(Vec::new()));
}

/// Handle incoming browser console logs
pub async fn handle_logs(
    Json(payload): Json<LogRequest>,
) -> Result<Json<serde_json::Value>, StatusCode> {
    let log_count = payload.logs.len();
    match LOG_STORE.lock() {
        Ok(mut logs) => {
            logs.extend(payload.logs);
            // Keep only last 1000 logs to avoid memory growth
            let current_len = logs.len();
            if current_len > 1000 {
                logs.drain(0..current_len - 1000);
            }
            tracing::debug!(
                "📝 Received {} log entries, total: {}",
                log_count,
                logs.len()
            );
            Ok(Json(serde_json::json!({ "status": "ok" })))
        }
        Err(e) => {
            tracing::error!("Failed to lock log store: {}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}

/// Get all captured logs
pub async fn get_logs() -> Result<Json<Vec<LogEntry>>, StatusCode> {
    match LOG_STORE.lock() {
        Ok(logs) => Ok(Json(logs.clone())),
        Err(e) => {
            tracing::error!("Failed to lock log store: {}", e);
            Err(StatusCode::INTERNAL_SERVER_ERROR)
        }
    }
}

/// Serve the logs viewer page
pub async fn logs_page() -> Html<&'static str> {
    Html(
        r#"
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Browser Console Logs Viewer</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Monaco', 'Courier New', monospace;
            background: #1e1e1e;
            color: #d4d4d4;
            padding: 20px;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
        }

        header {
            margin-bottom: 20px;
        }

        h1 {
            font-size: 24px;
            margin-bottom: 10px;
            color: #4ec9b0;
        }

        .controls {
            display: flex;
            gap: 10px;
            margin-bottom: 20px;
        }

        button {
            padding: 8px 16px;
            background: #0e639c;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
        }

        button:hover {
            background: #1177bb;
        }

        .filter-buttons button {
            padding: 6px 12px;
            font-size: 12px;
            background: #2d2d2d;
            color: #d4d4d4;
            border: 1px solid #555;
        }

        .filter-buttons button.active {
            background: #0e639c;
            color: white;
            border-color: #0e639c;
        }

        .stats {
            background: #252526;
            padding: 12px;
            border-radius: 4px;
            margin-bottom: 20px;
            font-size: 13px;
            border-left: 4px solid #4ec9b0;
        }

        .stats-item {
            display: inline-block;
            margin-right: 20px;
        }

        #logs-container {
            background: #1e1e1e;
            border: 1px solid #3e3e42;
            border-radius: 4px;
            overflow: auto;
            max-height: 600px;
            padding: 0;
        }

        .log-entry {
            padding: 10px 15px;
            border-bottom: 1px solid #3e3e42;
            font-size: 12px;
            line-height: 1.4;
            display: flex;
            gap: 10px;
        }

        .log-entry:hover {
            background: #2d2d30;
        }

        .log-timestamp {
            color: #858585;
            flex-shrink: 0;
            min-width: 200px;
        }

        .log-level {
            flex-shrink: 0;
            min-width: 60px;
            font-weight: bold;
        }

        .log-level.LOG {
            color: #6a9955;
        }

        .log-level.ERROR {
            color: #f48771;
        }

        .log-level.WARN {
            color: #dcdcaa;
        }

        .log-level.INFO {
            color: #4ec9b0;
        }

        .log-level.DEBUG {
            color: #9cdcfe;
        }

        .log-message {
            flex: 1;
            word-break: break-word;
            white-space: pre-wrap;
        }

        .empty-state {
            text-align: center;
            padding: 40px 20px;
            color: #858585;
        }

        .footer {
            margin-top: 20px;
            text-align: center;
            font-size: 12px;
            color: #858585;
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>🔍 Browser Console Logs</h1>
            <p>Real-time capture of browser console output</p>
        </header>

        <div class="stats" id="stats">
            <div class="stats-item">Total Logs: <strong id="total-count">0</strong></div>
            <div class="stats-item">Errors: <strong id="error-count" style="color: #f48771;">0</strong></div>
            <div class="stats-item">Warnings: <strong id="warn-count" style="color: #dcdcaa;">0</strong></div>
            <div class="stats-item">Last Updated: <strong id="last-update">Never</strong></div>
        </div>

        <div class="controls">
            <button onclick="clearLogs()">Clear All</button>
            <button onclick="toggleAutoRefresh()" id="auto-refresh-btn">Auto-Refresh: ON</button>
            <div class="filter-buttons" style="display: flex; gap: 5px;">
                <button class="active" onclick="filterLogs('all')" data-filter="all">All</button>
                <button onclick="filterLogs('ERROR')" data-filter="ERROR">Errors</button>
                <button onclick="filterLogs('WARN')" data-filter="WARN">Warnings</button>
                <button onclick="filterLogs('LOG')" data-filter="LOG">Logs</button>
            </div>
        </div>

        <div id="logs-container">
            <div class="empty-state">
                <p>Waiting for console output...</p>
                <p style="font-size: 11px; margin-top: 10px;">Logs will appear here as they are captured</p>
            </div>
        </div>

        <div class="footer">
            <p>This page captures all browser console output in real-time. Refresh the page to continue monitoring.</p>
        </div>
    </div>

    <script>
        let autoRefresh = true;
        let currentFilter = 'all';
        let allLogs = [];

        async function fetchLogs() {
            try {
                const response = await fetch('/api/logs');
                if (!response.ok) {
                    console.error('Failed to fetch logs:', response.status);
                    return;
                }

                allLogs = await response.json();
                renderLogs();
                updateStats();
                updateTimestamp();
            } catch (e) {
                console.error('Error fetching logs:', e);
            }
        }

        function renderLogs() {
            const container = document.getElementById('logs-container');

            const filteredLogs = allLogs.filter(log => {
                return currentFilter === 'all' || log.level === currentFilter;
            });

            if (filteredLogs.length === 0) {
                container.innerHTML = '<div class="empty-state"><p>No logs match the current filter</p></div>';
                return;
            }

            container.innerHTML = filteredLogs.map(log => `
                <div class="log-entry">
                    <span class="log-timestamp">${new Date(log.timestamp).toLocaleTimeString()}</span>
                    <span class="log-level ${log.level}">${log.level}</span>
                    <span class="log-message">${escapeHtml(log.message)}</span>
                </div>
            `).join('');

            // Auto-scroll to bottom
            container.scrollTop = container.scrollHeight;
        }

        function updateStats() {
            document.getElementById('total-count').textContent = allLogs.length;
            document.getElementById('error-count').textContent = allLogs.filter(l => l.level === 'ERROR').length;
            document.getElementById('warn-count').textContent = allLogs.filter(l => l.level === 'WARN').length;
        }

        function updateTimestamp() {
            const now = new Date();
            document.getElementById('last-update').textContent = now.toLocaleTimeString();
        }

        function clearLogs() {
            if (confirm('Clear all logs?')) {
                allLogs = [];
                renderLogs();
                updateStats();
            }
        }

        function toggleAutoRefresh() {
            autoRefresh = !autoRefresh;
            const btn = document.getElementById('auto-refresh-btn');
            btn.textContent = `Auto-Refresh: ${autoRefresh ? 'ON' : 'OFF'}`;
            btn.style.background = autoRefresh ? '#0e639c' : '#2d2d2d';
        }

        function filterLogs(level) {
            currentFilter = level;
            document.querySelectorAll('.filter-buttons button').forEach(btn => {
                btn.classList.toggle('active', btn.dataset.filter === level);
            });
            renderLogs();
        }

        function escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }

        // Initial load
        fetchLogs();

        // Auto-refresh every 1 second if enabled
        setInterval(() => {
            if (autoRefresh) {
                fetchLogs();
            }
        }, 1000);
    </script>
</body>
</html>
    "#,
    )
}
