import $ from 'jquery';
import { JSONRPC } from '@/json-rpc.js';

const MAX_PREVIEW_LENGTH = "[06.10.2025 01:14:00][SEVERE] ShellExecutor> Failed to execute local shell command \"rc-service openvpn restart\"\r\nIOException:Cannot run program \"rc-service openvpn restart\": Exec failed, error: 2 (Нет такого файла или каталога) \nStack trace:\njava.base/".length;

let logs = [];
let hasRendered = false;
let isLoading = false;
let refreshIntervalId = null;

const FIELD_IDS = {
    container: 'logs-container',
    list: 'logs-list',
    refreshButton: 'logs-refresh-btn',
    clearButton: 'logs-clear-btn',
    status: 'logs-status-message'
};

function escapeHtml(value = '') {
    return value
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;');
}

function normalizeLevel(level) {
    if (typeof level !== 'string') {
        return '';
    }
    return level.replace(/[\[\]\s]/g, '').toUpperCase();
}

function getLevelClass(level) {
    const normalized = normalizeLevel(level);
    if (normalized === 'SEVERE') {
        return 'log-level-severe';
    }
    if (normalized === 'WARNING') {
        return 'log-level-warning';
    }
    if (normalized === 'INFO') {
        return 'log-level-info';
    }
    return '';
}

function trimQuotes(value) {
    if (!value) {
        return value;
    }
    if (value.startsWith('"') && value.endsWith('"')) {
        return value.slice(1, -1);
    }
    return value;
}

function getMessage(entry) {
    if (entry?.message) {
        return trimQuotes(String(entry.message));
    }
    if (entry?.msg) {
        return trimQuotes(String(entry.msg));
    }
    if (typeof entry === 'string') {
        return trimQuotes(entry);
    }
    return JSON.stringify(entry);
}

function getPreviewHtml(fullMessage, index) {
    if (fullMessage.length <= MAX_PREVIEW_LENGTH) {
        return escapeHtml(fullMessage);
    }

    const preview = escapeHtml(fullMessage.slice(0, MAX_PREVIEW_LENGTH));
    return `${preview}... <a href="#" class="log-entry-expand" data-index="${index}" style="color: var(--color-primary);">показать полностью</a>`;
}

function createLogEntryHtml(entry, index) {
    const timestamp = entry.timestamp || entry.time || '';
    let level = entry.level || entry.severity || '';
    const message = getMessage(entry);

    let normalizedLevel = normalizeLevel(level);
    if (!normalizedLevel) {
        const match = message.match(/\[(INFO|WARNING|SEVERE)\]/i);
        if (match) {
            normalizedLevel = match[1].toUpperCase();
            level = normalizedLevel;
        }
    }

    const levelLabel = normalizedLevel ? `[${normalizedLevel}]` : '';
    const levelClass = getLevelClass(normalizedLevel);
    const previewHtml = getPreviewHtml(message, index);

    return `
        <div class="log-entry ${levelClass}" data-index="${index}" style="border-bottom: 1px solid var(--color-border); padding: 12px 16px;">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px;">
                <span class="log-entry-timestamp" style="color: var(--color-text-secondary); font-size: 13px;">${escapeHtml(timestamp)}</span>
                <span class="log-entry-level">${escapeHtml(levelLabel)}</span>
            </div>
            <div class="log-entry-message" data-full="${encodeURIComponent(message)}">${previewHtml}</div>
        </div>
    `;
}

function serializeLogEntry(entry) {
    if (Array.isArray(entry)) {
        return `[${entry.map(serializeLogEntry).join(',')}]`;
    }

    if (entry && typeof entry === 'object') {
        const keys = Object.keys(entry).sort();
        const serialized = keys.map((key) => `${JSON.stringify(key)}:${serializeLogEntry(entry[key])}`);
        return `{${serialized.join(',')}}`;
    }

    return JSON.stringify(entry);
}

function haveLogsChanged(previousLogs, nextLogs) {
    if (previousLogs === nextLogs) {
        return false;
    }

    if (!Array.isArray(previousLogs) || !Array.isArray(nextLogs)) {
        return true;
    }

    if (previousLogs.length !== nextLogs.length) {
        return true;
    }

    for (let index = 0; index < previousLogs.length; index += 1) {
        if (serializeLogEntry(previousLogs[index]) !== serializeLogEntry(nextLogs[index])) {
            return true;
        }
    }

    return false;
}

function renderLogs() {
    const $list = $(`#${FIELD_IDS.list}`);
    hasRendered = true;
    if (!logs.length) {
        $list.html('<p style="color: var(--color-text-secondary);">Записей в журнале нет.</p>');
        return;
    }

    const entriesHtml = logs.map(createLogEntryHtml).join('');
    $list.html(entriesHtml);
    $list.scrollTop($list.prop('scrollHeight'));
}

async function loadLogs() {
    if (isLoading) {
        return;
    }
    isLoading = true;
    const $status = $(`#${FIELD_IDS.status}`);
    $status.hide().removeClass('error-message success-message');

    try {
        const entries = await JSONRPC.System.getLogs();
        const nextLogs = Array.isArray(entries) ? entries : [];
        const shouldRender = !hasRendered || haveLogsChanged(logs, nextLogs);

        if (!shouldRender) {
            return;
        }

        logs = nextLogs.slice();
        renderLogs();
    } catch (error) {
        console.error('Ошибка загрузки логов:', error);
        $status.text('Не удалось загрузить журнал.').addClass('error-message').show();
    } finally {
        isLoading = false;
    }
}

function attachEventHandlers() {
    $(`#${FIELD_IDS.refreshButton}`).off('click').on('click', () => loadLogs());
    $(`#${FIELD_IDS.clearButton}`).off('click').on('click', async () => {
        const $btn = $(`#${FIELD_IDS.clearButton}`);
        const $status = $(`#${FIELD_IDS.status}`);
        $btn.prop('disabled', true).text('Очистка...');
        $status.hide().removeClass('error-message success-message');

        try {
            await JSONRPC.System.clearLogs();
            await loadLogs();
            $status.text('Журнал очищен.').removeClass('error-message').addClass('success-message').show();
        } catch (error) {
            console.error('Ошибка очистки журналов:', error);
            $status.text('Не удалось очистить журнал.').removeClass('success-message').addClass('error-message').show();
        } finally {
            $btn.prop('disabled', false).text('Очистить');
        }
    });
    $(document)
        .off('click', '.log-entry-expand')
        .on('click', '.log-entry-expand', function (event) {
            event.preventDefault();
            const $message = $(this).closest('.log-entry-message');
            const full = decodeURIComponent($message.data('full'));
            $message.html(`${escapeHtml(full)} <a href="#" class="log-entry-collapse" style="color: var(--color-primary);">скрыть</a>`);
        })
        .off('click', '.log-entry-collapse')
        .on('click', '.log-entry-collapse', function (event) {
            event.preventDefault();
            const $message = $(this).closest('.log-entry-message');
            const full = decodeURIComponent($message.data('full'));
            const index = $(this).closest('.log-entry').data('index') || 0;
            const previewHtml = getPreviewHtml(full, index);
            $message.html(previewHtml);
        });
}

function detachEventHandlers() {
    $(`#${FIELD_IDS.refreshButton}`).off('click');
    $(`#${FIELD_IDS.clearButton}`).off('click');
    $(document).off('click', '.log-entry-expand');
    $(document).off('click', '.log-entry-collapse');
}

export const LogsPage = {
    render: () => `
        <h1 class="page-title">Журнал</h1>
        <div class="component-config-form" style="max-width: none; width: 100%;">
            <div class="action-buttons" style="justify-content: flex-start; margin-bottom: 20px; gap: 12px;">
                <button id="${FIELD_IDS.refreshButton}" class="btn-secondary" style="width: 200px;">Обновить</button>
                <button id="${FIELD_IDS.clearButton}" class="btn-secondary" style="width: 200px;">Очистить</button>
            </div>
            <div id="${FIELD_IDS.status}" class="error-message" style="display: none; margin-bottom: 10px;"></div>
            <div id="${FIELD_IDS.list}" style="max-height: 480px; overflow-y: auto; border: 1px solid var(--color-border); border-radius: 8px; background: var(--color-bg-card);"></div>
        </div>
    `,
    mount: async () => {
        attachEventHandlers();
        await loadLogs();
        if (refreshIntervalId) {
            clearInterval(refreshIntervalId);
        }
        refreshIntervalId = setInterval(loadLogs, 10000);
    },
    unmount: () => {
        detachEventHandlers();
        logs = [];
        hasRendered = false;
        isLoading = false;
        if (refreshIntervalId) {
            clearInterval(refreshIntervalId);
            refreshIntervalId = null;
        }
    }
};
