<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>aiosyslogd Log Viewer</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <style>
        body { font-family: 'Inter', sans-serif; }
        .search-bar {
            box-shadow: 0 1px 6px rgba(32, 33, 36, 0.28);
            border-radius: 24px;
        }
        .search-bar:hover {
            box-shadow: 0 2px 8px rgba(32, 33, 36, 0.35);
        }
        /* Styles for highlighted text */
        .highlight-span {
            padding: 1px 4px;
            border-radius: 4px;
            font-weight: 500;
        }
    </style>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&display=swap" rel="stylesheet">
</head>
<body class="bg-gray-100 text-gray-800">

<div class="container mx-auto p-4 md:p-8">
    <header class="text-center mb-8">
        <h1 class="text-4xl font-bold text-gray-700">aiosyslogd Log Viewer</h1>
        <p class="text-gray-500">SQLite Log Search Interface</p>
    </header>

    <!-- Search and Filter Form -->
    <form action="{{ url_for('index') }}" method="get" class="bg-white p-6 rounded-lg shadow-md mb-8">
        <!-- Database Selector -->
        <div class="mb-4">
            <label for="db_file" class="block text-sm font-medium text-gray-700 mb-1">Database File</label>
            <select name="db_file" id="db_file" class="w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500" onchange="this.form.submit()">
                {% for db in available_dbs %}
                    <option value="{{ db }}" {% if db == selected_db %}selected{% endif %}>{{ db }}</option>
                {% endfor %}
            </select>
        </div>

        <!-- Main Search Bar -->
        <div class="flex items-center space-x-2 mb-4">
            <div class="relative w-full">
                <input type="text" name="q" value="{{ search_query }}" placeholder="Enter FTS5 query for Message (e.g., 'error* OR failure')" class="w-full py-3 pl-4 pr-12 text-lg border-gray-300 search-bar focus:ring-indigo-500 focus:border-indigo-500">
                <div class="absolute inset-y-0 right-0 flex py-1.5 pr-1.5">
                    <button type="submit" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-full shadow-sm text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
                        <svg class="h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
                        </svg>
                    </button>
                </div>
            </div>
            <a href="{{ url_for('index', db_file=selected_db) }}" class="flex-shrink-0 inline-flex items-center justify-center h-[52px] w-[52px] border border-gray-300 rounded-full text-gray-500 bg-white hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" title="Reset Search and Filters">
                <svg class="h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
                </svg>
            </a>
        </div>

        <!-- Advanced Filters -->
        <div class="flex justify-between items-center mb-2">
             <h3 class="text-lg font-medium text-gray-800">Advanced Filters</h3>
             <!-- MODIFIED: Changed from a link to a button -->
             <button type="button" id="toggle-sql-btn" class="text-sm text-indigo-600 hover:text-indigo-800">Show Executed SQL</button>
        </div>
        <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 border-t pt-4">
            <input type="hidden" name="last_id" value=""> <!-- Clear last_id when filters change -->
            <div>
                <label for="from_host" class="block text-sm font-medium text-gray-700">FromHost</label>
                <input type="text" name="from_host" id="from_host" value="{{ filters.from_host or '' }}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
            </div>
            <div>
                <label for="received_at_min" class="block text-sm font-medium text-gray-700">Received At (Start)</label>
                <input type="datetime-local" name="received_at_min" id="received_at_min" value="{{ filters.received_at_min or '' }}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
            </div>
            <div>
                <label for="received_at_max" class="block text-sm font-medium text-gray-700">Received At (End)</label>
                <input type="datetime-local" name="received_at_max" id="received_at_max" value="{{ filters.received_at_max or '' }}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
            </div>
        </div>

        <!-- Debug SQL Query -->
        <!-- MODIFIED: The box is now always rendered but hidden by default -->
        {% if debug_query %}
        <div id="sql-query-box" class="bg-gray-800 text-white p-4 rounded-lg shadow-inner mt-4 hidden">
            <h3 class="font-bold mb-2 text-gray-400 uppercase tracking-wider text-xs">Executed SQL Query</h3>
            <pre class="font-mono text-sm whitespace-pre-wrap"><code>{{ debug_query }}</code></pre>
        </div>
        {% endif %}
    </form>

    <!-- Key Highlighter UI -->
    <div class="bg-white p-4 rounded-lg shadow-md mb-8">
        <h3 class="text-lg font-medium text-gray-800 mb-2">Dynamic Highlighter</h3>
        <div class="flex items-center space-x-2">
            <input type="text" id="key-extractor-input" placeholder="Enter key to highlight" class="w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500">
            <button type="button" id="add-highlight-btn" class="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-indigo-600 hover:bg-indigo-700">Highlight Key</button>
            <button type="button" id="remove-highlights-btn" class="inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md shadow-sm text-gray-700 bg-white hover:bg-gray-50">Remove All</button>
        </div>
        <div class="mt-2 text-sm text-gray-600">
            <strong>Highlighted Keys:</strong> <span id="highlighted-keys-list">None</span>
        </div>
    </div>


    <!-- Results Count -->
    {% if total_logs is not none %}
    <div class="mb-4 text-gray-600">
        Found <span class="font-bold">{{ "{:,}".format(total_logs) }}</span> matching logs
        {% if query_time is not none %}
         in <span class="font-bold">{{ "%.3f"|format(query_time) }}s</span>.
        {% endif %}
    </div>
    {% endif %}

    <!-- Results -->
    {% if error %}
        <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded-lg relative" role="alert">
            <strong class="font-bold">Query Error:</strong>
            <span class="block sm:inline">{{ error }}</span>
        </div>
    {% elif logs %}
        <div id="log-table" class="bg-white shadow-md rounded-lg overflow-hidden font-mono">

            <div class="log-table-header hidden md:grid md:grid-cols-[6rem_2fr_2fr_7fr] md:gap-x-4 bg-gray-50 font-medium text-xs text-gray-500 uppercase tracking-wider border-b border-gray-200">
                <div class="px-4 py-2 text-right">ID</div>
                <div class="px-4 py-2">Received At</div>
                <div class="px-4 py-2">From Host</div>
                <div class="px-4 py-2">Message</div>
            </div>

            <div class="divide-y divide-gray-200">
                {% for log in logs %}
                <div class="log-row md:grid md:grid-cols-[6rem_2fr_2fr_7fr] md:gap-x-4 md:items-center">

                    <div class="md:hidden space-y-1 p-3">
                        <div>
                            <span class="font-bold text-gray-600">ID:</span>
                            <span class="text-gray-800">{{ log.ID }}</span>
                        </div>
                        <div>
                            <span class="font-bold text-gray-600">Received At:</span>
                            <span class="text-gray-800">{{ log.ReceivedAt.strftime('%Y-%m-%d %H:%M:%S') }}</span>
                        </div>
                        <div>
                            <span class="font-bold text-gray-600">From Host:</span>
                            <span class="text-gray-800">{{ log.FromHost }}</span>
                        </div>
                        <div>
                            <span class="font-bold text-gray-600">Message:</span>
                            <p class="text-gray-900 break-all log-message-cell">{{ log.Message }}</p>
                        </div>
                    </div>

                    <div class="hidden md:contents">
                        <div class="px-4 py-2 whitespace-nowrap text-sm text-gray-500 text-right">{{ log.ID }}</div>
                        <div class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">{{ log.ReceivedAt.strftime('%Y-%m-%d %H:%M:%S') }}</div>
                        <div class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">{{ log.FromHost }}</div>
                        <div class="px-4 py-2 text-sm text-gray-900 break-all log-message-cell">{{ log.Message }}</div>
                    </div>
                </div>
                {% endfor %}
            </div>
        </div>
    {% else %}
        <div class="text-center py-12 bg-white rounded-lg shadow-md">
            <p class="text-gray-500">No logs found. Try adjusting your search.</p>
        </div>
    {% endif %}

    <!-- Pagination -->
    <div class="flex justify-between items-center mt-6">
        <div>
           {% if page_info.has_prev_page %}
             {% set prev_args = request.args.to_dict() %}
             {% do prev_args.update({'last_id': page_info.prev_last_id, 'direction': 'prev'}) %}
             <a href="{{ url_for('index', **prev_args) }}" class="inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">
                Previous
            </a>
            {% endif %}
        </div>
        <div>
            {% if page_info.has_next_page %}
             {% set next_args = request.args.to_dict() %}
             {% do next_args.update({'last_id': page_info.next_last_id, 'direction': 'next'}) %}
             <a href="{{ url_for('index', **next_args) }}" class="inline-flex items-center px-4 py-2 border border-gray-300 text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50">
                Next
            </a>
            {% endif %}
        </div>
    </div>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
    // --- STATE ---
    let originalCasingKeys = []; // Stores original keys for display and URL
    const keyInput = document.getElementById('key-extractor-input');
    const addHighlightButton = document.getElementById('add-highlight-btn');
    const removeHighlightsButton = document.getElementById('remove-highlights-btn');
    const highlightedKeysList = document.getElementById('highlighted-keys-list');
    const toggleSqlButton = document.getElementById('toggle-sql-btn');
    const sqlQueryBox = document.getElementById('sql-query-box');

    const highlightColors = [
        'bg-green-100 text-green-800',
        'bg-yellow-100 text-yellow-800',
        'bg-blue-100 text-blue-800',
        'bg-purple-100 text-purple-800',
        'bg-pink-100 text-pink-800',
        'bg-indigo-100 text-indigo-800'
    ];
    let keyColorMap = {};

    // --- MAIN FUNCTIONS ---
    function applyAllHighlights() {
        const messageCells = document.querySelectorAll('.log-message-cell');
        messageCells.forEach(cell => {
            if (cell.dataset.originalText) {
                cell.innerHTML = cell.dataset.originalText;
            } else {
                cell.dataset.originalText = cell.innerHTML;
            }

            let newHtml = cell.innerHTML;
            originalCasingKeys.forEach(key => {
                const sanitizedKey = key.replace(/[^a-zA-Z0-9_-]/g, '');
                const lowerCaseKey = sanitizedKey.toLowerCase();
                const colorClass = keyColorMap[lowerCaseKey];

                const regex = new RegExp(`(${sanitizedKey}(?:\\s*=\\s*|\\s+)(?:'[^']+'|"[^"]+"|[\\S]+))`, 'gi');

                newHtml = newHtml.replace(regex, (match) => {
                    if (match.startsWith('<span')) return match;
                    return `<span class="highlight-span ${colorClass}">${match}</span>`;
                });
            });
            cell.innerHTML = newHtml;
        });
    }

    function addHighlightKey(key) {
        const sanitizedKey = key.replace(/[^a-zA-Z0-9_-]/g, '');
        const lowerCaseKey = sanitizedKey.toLowerCase();

        const alreadyExists = originalCasingKeys.some(k => k.toLowerCase() === lowerCaseKey);
        if (!sanitizedKey || alreadyExists) {
            console.warn(`Key "${sanitizedKey}" is empty or already highlighted.`);
            return;
        }

        originalCasingKeys.push(sanitizedKey);
        keyColorMap[lowerCaseKey] = highlightColors[originalCasingKeys.length - 1 % highlightColors.length];

        updatePaginationLinks();
        updateKeyListUI();
        applyAllHighlights();
    }

    function resetHighlights() {
        const url = new URL(window.location.href);
        url.searchParams.delete('extract');
        window.location.href = url.toString();
    }

    function updateKeyListUI() {
        if (originalCasingKeys.length > 0) {
            highlightedKeysList.innerHTML = '';
            originalCasingKeys.forEach(key => {
                const lowerCaseKey = key.toLowerCase();
                const colorClass = keyColorMap[lowerCaseKey];
                const span = document.createElement('span');
                span.className = `highlight-span mr-2 ${colorClass}`;
                span.textContent = key;
                highlightedKeysList.appendChild(span);
            });
            removeHighlightsButton.style.display = 'inline-flex';
        } else {
            highlightedKeysList.textContent = 'None';
            removeHighlightsButton.style.display = 'none';
        }
    }

    function updatePaginationLinks() {
        const paginationLinks = document.querySelectorAll('div.flex.justify-between a');

        paginationLinks.forEach(link => {
            let href = new URL(link.href, window.location.origin);
            href.searchParams.delete('extract');
            if (originalCasingKeys.length > 0) {
                 href.searchParams.set('extract', originalCasingKeys.join(','));
            }
            link.href = href.toString();
        });
    }

    // --- EVENT LISTENERS ---
    addHighlightButton.addEventListener('click', () => {
        const newKey = keyInput.value.trim();
        if (newKey) {
            addHighlightKey(newKey);
            keyInput.value = '';
        }
    });

    removeHighlightsButton.addEventListener('click', resetHighlights);

    keyInput.addEventListener('keydown', (e) => {
        if (e.key === 'Enter') {
            e.preventDefault();
            addHighlightButton.click();
        }
    });

    if (toggleSqlButton) {
        toggleSqlButton.addEventListener('click', () => {
            if (sqlQueryBox) {
                const isHidden = sqlQueryBox.classList.toggle('hidden');
                toggleSqlButton.textContent = isHidden ? 'Show Executed SQL' : 'Hide Executed SQL';
            }
        });
    }

    // --- ON PAGE LOAD ---
    function initialize() {
        const urlParams = new URLSearchParams(window.location.search);
        const keysToExtract = urlParams.get('extract');
        if (keysToExtract) {
            const keys = keysToExtract.split(',');
            keys.forEach(key => {
                 addHighlightKey(key.trim());
            });
        } else {
            updateKeyListUI();
            updatePaginationLinks();
        }
    }

    initialize();
});
</script>

</body>
</html>
