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

const OVPN_COMPONENT_NAME = 'ru.kirillius.pf.sdn.External.API.Components.OVPN';
const DEFAULT_PORT = 22;

const FIELD_IDS = {
    host: 'ovpn-host',
    port: 'ovpn-port',
    username: 'ovpn-username',
    password: 'ovpn-password',
    useSSH: 'ovpn-use-ssh',
    restartCommand: 'ovpn-restart-command',
    restartOnUpdate: 'ovpn-restart-on-update',
    saveButton: 'save-ovpn-btn',
    restartButton: 'restart-ovpn-btn',
    status: 'ovpn-status-message',
    container: 'ovpn-config-container'
};

const SELECTORS = {
    container: `#${FIELD_IDS.container}`,
    host: `#${FIELD_IDS.host}`,
    port: `#${FIELD_IDS.port}`,
    username: `#${FIELD_IDS.username}`,
    password: `#${FIELD_IDS.password}`,
    useSSH: `#${FIELD_IDS.useSSH}`,
    restartCommand: `#${FIELD_IDS.restartCommand}`,
    restartOnUpdate: `#${FIELD_IDS.restartOnUpdate}`,
    saveButton: `#${FIELD_IDS.saveButton}`,
    restartButton: `#${FIELD_IDS.restartButton}`,
    status: `#${FIELD_IDS.status}`
};

const CLASS_NAMES = {
    shellFields: 'ovpn-shell-fields'
};

let currentConfig = {};
let statusTimeoutId = null;

const getStatusElement = () => $(SELECTORS.status);

function clearStatus() {
    const $status = getStatusElement();
    if (!$status.length) {
        return;
    }
    if (statusTimeoutId) {
        clearTimeout(statusTimeoutId);
        statusTimeoutId = null;
    }
    $status.stop(true, true).hide().text('').removeClass('success-message error-message');
}

function updateStatus(message, type) {
    const $status = getStatusElement();
    if (!$status.length) {
        return;
    }
    if (statusTimeoutId) {
        clearTimeout(statusTimeoutId);
    }
    $status
        .removeClass('success-message error-message')
        .addClass(type === 'success' ? 'success-message' : 'error-message')
        .text(message)
        .show();

    statusTimeoutId = window.setTimeout(() => {
        $status.fadeOut();
    }, 5000);
}

async function runAction($button, pendingText, action, messages) {
    if (!$button.length) {
        return;
    }

    const originalText = $button.text();
    $button.prop('disabled', true).text(pendingText);
    clearStatus();

    try {
        const result = await action();
        if (messages?.success) {
            const successMessage = typeof messages.success === 'function'
                ? messages.success(result)
                : messages.success;
            if (successMessage) {
                updateStatus(successMessage, 'success');
            }
        }
    } catch (error) {
        console.error(messages?.log || 'Ошибка выполнения действия OVPN:', error);
        if (messages?.error) {
            updateStatus(messages.error, 'error');
        }
    } finally {
        $button.prop('disabled', false).text(originalText);
    }
}

async function loadConfig() {
    try {
        const fullConfig = await JSONRPC.System.getComponentConfig(OVPN_COMPONENT_NAME);
        currentConfig = fullConfig || {};
        return true;
    } catch (error) {
        console.error('Ошибка при загрузке конфига OVPN:', error);
        return false;
    }
}

function renderOVPNForm() {
    const $container = $(SELECTORS.container);
    const shellConfig = currentConfig.shellConfig || {};
    const shellFieldsStyle = shellConfig.useSSH ? '' : 'display: none;';

    $container.html(`
        <div class="component-config-form">
            <h3 class="config-section-title">Конфигурация Shell (ShellConfig)</h3>
            <div class="form-group checkbox-group">
                <input type="checkbox" id="${FIELD_IDS.useSSH}" ${shellConfig.useSSH ? 'checked' : ''}>
                <label for="${FIELD_IDS.useSSH}" style="margin-bottom: 0;">Использовать SSH</label>
            </div>
            <div class="${CLASS_NAMES.shellFields}" style="${shellFieldsStyle}">
                <div class="form-group">
                    <label for="${FIELD_IDS.host}">Хост</label>
                    <input type="text" id="${FIELD_IDS.host}" class="form-control" value="${shellConfig.host || ''}">
                </div>
                <div class="form-group">
                    <label for="${FIELD_IDS.port}">Порт</label>
                    <input type="number" id="${FIELD_IDS.port}" class="form-control" value="${shellConfig.port || DEFAULT_PORT}">
                </div>
                <div class="form-group">
                    <label for="${FIELD_IDS.username}">Имя пользователя</label>
                    <input type="text" id="${FIELD_IDS.username}" class="form-control" value="${shellConfig.username || ''}">
                </div>
                <div class="form-group">
                    <label for="${FIELD_IDS.password}">Пароль</label>
                    <input type="password" id="${FIELD_IDS.password}" class="form-control" placeholder="Оставьте пустым для сохранения текущего пароля">
                </div>
            </div>
            
            <h3 class="config-section-title" style="margin-top: 40px;">Перезапуск сервиса</h3>
            <div class="form-group">
                <label for="${FIELD_IDS.restartCommand}">Команда для перезапуска</label>
                <input type="text" id="${FIELD_IDS.restartCommand}" class="form-control" value="${currentConfig.restartCommand || 'systemctl restart openvpn@server'}">
                <small class="hint-text">Команда, которая будет выполнена через Shell для перезапуска сервиса OVPN.</small>
            </div>
            <div class="form-group checkbox-group">
                <input type="checkbox" id="${FIELD_IDS.restartOnUpdate}" ${currentConfig.restartOnUpdate ? 'checked' : ''}>
                <label for="${FIELD_IDS.restartOnUpdate}" style="margin-bottom: 0;">Перезапускать сервис после обновления</label>
            </div>
            
            <div class="action-buttons">
                <button id="${FIELD_IDS.saveButton}" class="btn-primary" style="width: 200px;">Применить Конфигурацию</button>
                <button id="${FIELD_IDS.restartButton}" class="btn-secondary" style="width: 200px; margin-left: 20px;">Перезапустить Сервис</button>
            </div>
            <div id="${FIELD_IDS.status}" class="error-message" style="display: none;"></div>
            <div class="config-hint" style="margin-top: 30px;">
                <h3 class="config-section-title">Дополнительная настройка</h3>
                <p>В файле <code>openvpn.conf</code> необходимо добавить следующие директивы:</p>
                <pre style="white-space: pre-wrap;">script-security 2
client-connect /usr/bin/ovpn-pfsdn-bind</pre>
                <p>Также создайте файл <code>ovpn-connector.json</code> со структурой:</p>
                <pre style="white-space: pre-wrap;">{
    "token": "string",
    "host": "string"
}</pre>
                <p>Токен создаётся на странице API, а значение <code>host</code> должно указывать на адрес вида <code>http://127.0.0.1:8080</code>.</p>
            </div>
        </div>
    `);

    attachEventHandlers();
}

function collectConfigFromForm() {
    const shellConfig = currentConfig.shellConfig || {};
    const newPassword = $(SELECTORS.password).val();
    const useSSH = $(SELECTORS.useSSH).prop('checked');

    return {
        shellConfig: {
            useSSH,
            host: $(SELECTORS.host).val(),
            port: parseInt($(SELECTORS.port).val(), 10) || DEFAULT_PORT,
            username: $(SELECTORS.username).val(),
            password: newPassword ? newPassword : (shellConfig.password || ''),
        },
        restartCommand: $(SELECTORS.restartCommand).val(),
        restartOnUpdate: $(SELECTORS.restartOnUpdate).prop('checked')
    };
}

async function handleSave() {
    const $button = $(SELECTORS.saveButton);
    await runAction($button, 'Применение...', async () => {
        const newConfig = collectConfigFromForm();
        await JSONRPC.System.setComponentConfig(OVPN_COMPONENT_NAME, newConfig);
        currentConfig = newConfig;
    }, {
        success: 'Конфигурация OVPN успешно сохранена.',
        error: 'Ошибка при сохранении конфигурации.',
        log: 'Ошибка сохранения конфига OVPN'
    });
}

async function handleRestart() {
    const $button = $(SELECTORS.restartButton);
    await runAction($button, 'Перезапуск...', async () => {
        return JSONRPC.OVPN.restartSystemService();
    }, {
        success: (result) => result || 'Сервис OVPN успешно перезапущен.',
        error: 'Ошибка при перезапуске сервиса.',
        log: 'Ошибка перезапуска OVPN'
    });
}

function attachEventHandlers() {
    $(SELECTORS.saveButton).off('click').on('click', handleSave);
    $(SELECTORS.restartButton).off('click').on('click', handleRestart);
    $(SELECTORS.useSSH).off('change').on('change', toggleSSHFields);
    toggleSSHFields();
}

function detachEventHandlers() {
    $(SELECTORS.saveButton).off('click');
    $(SELECTORS.restartButton).off('click');
    $(SELECTORS.useSSH).off('change');
}

function toggleSSHFields() {
    const enabled = $(SELECTORS.useSSH).prop('checked');
    const $shellFields = $(SELECTORS.container).find(`.${CLASS_NAMES.shellFields}`);
    $(SELECTORS.host).prop('disabled', !enabled);
    $(SELECTORS.port).prop('disabled', !enabled);
    $(SELECTORS.username).prop('disabled', !enabled);
    $(SELECTORS.password).prop('disabled', !enabled);
    $shellFields.toggle(enabled);
}

export const OVPNConfig = {
    render: () => `
        <h1 class="page-title">Настройка OVPN</h1>
        <div id="${FIELD_IDS.container}">
            <p>Загрузка конфигурации...</p>
        </div>
    `,
    mount: async () => {
        const success = await loadConfig();
        if (success) {
            renderOVPNForm();
        } else {
            $(SELECTORS.container).html('<p class="error-message">Не удалось загрузить конфигурацию OVPN.</p>');
        }
    },
    unmount: () => {
        detachEventHandlers();
        clearStatus();
        currentConfig = {};
    }
};