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

const FRR_COMPONENT_NAME = 'ru.kirillius.pf.sdn.External.API.Components.FRR';
const DEFAULT_PORT = 22;
const DEFAULT_SUBNET_PATTERN = 'ip route {%subnet} {%gateway} 100';

const FIELD_IDS = {
    container: 'frr-config-container',
    instancesList: 'frr-instances-list',
    addInstanceButton: 'frr-add-instance-btn',
    saveButton: 'save-frr-btn',
    status: 'frr-status-message'
};

const CLASS_NAMES = {
    instance: 'frr-instance-entry',
    removeInstanceButton: 'frr-remove-instance-btn',
    shellUseSSH: 'frr-shell-use-ssh',
    shellSection: 'frr-shell-section',
    shellHost: 'frr-shell-host',
    shellPort: 'frr-shell-port',
    shellUsername: 'frr-shell-username',
    shellPassword: 'frr-shell-password',
    subnetPattern: 'frr-subnet-pattern',
    gateway: 'frr-gateway',
    essentialList: 'frr-essential-list',
    essentialItem: 'frr-essential-item',
    essentialInput: 'frr-essential-input',
    addEssentialButton: 'frr-add-essential-btn',
    removeEssentialButton: 'frr-remove-essential-btn'
};

const SELECTORS = {
    container: `#${FIELD_IDS.container}`,
    instancesList: `#${FIELD_IDS.instancesList}`,
    addInstanceButton: `#${FIELD_IDS.addInstanceButton}`,
    saveButton: `#${FIELD_IDS.saveButton}`,
    status: `#${FIELD_IDS.status}`
};

let currentConfig = { instances: [] };
let statusTimeoutId = null;
let instanceCounter = 0;
let essentialCounters = {};

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

function normalizeConfig(config) {
    if (!config || !Array.isArray(config.instances)) {
        return { instances: [] };
    }

    return {
        instances: config.instances.map(instance => {
            const shellConfig = instance?.shellConfig || {};
            return {
                shellConfig: {
                    useSSH: !!shellConfig.useSSH,
                    host: shellConfig.host || '',
                    port: Number.isInteger(shellConfig.port) ? shellConfig.port : DEFAULT_PORT,
                    username: shellConfig.username || '',
                    password: shellConfig.password || ''
                },
                subnetPattern: instance?.subnetPattern || DEFAULT_SUBNET_PATTERN,
                gateway: instance?.gateway || '',
                essentialSubnets: Array.isArray(instance?.essentialSubnets)
                    ? instance.essentialSubnets.filter(item => typeof item === 'string')
                    : []
            };
        })
    };
}

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 || 'Ошибка выполнения действия FRR:', error);
        if (messages?.error) {
            updateStatus(messages.error, 'error');
        }
    } finally {
        $button.prop('disabled', false).text(originalText);
    }
}

function resetCounters() {
    instanceCounter = 0;
    essentialCounters = {};
}

function getNextInstanceId() {
    instanceCounter += 1;
    return instanceCounter;
}

function getNextEssentialId(instanceId) {
    if (!essentialCounters[instanceId]) {
        essentialCounters[instanceId] = 0;
    }
    essentialCounters[instanceId] += 1;
    return essentialCounters[instanceId];
}

function isValidIPv4Cidr(value) {
    const cidrRegex = /^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}\/(3[0-2]|[12]?\d)$/;
    return cidrRegex.test(value);
}

function createEssentialSubnetRow(instanceId, value = '') {
    const essentialId = getNextEssentialId(instanceId);
    const inputId = `frr-essential-${instanceId}-${essentialId}`;

    return `
        <div class="${CLASS_NAMES.essentialItem}" style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;">
            <input type="text" id="${inputId}" class="form-control ${CLASS_NAMES.essentialInput}" placeholder="1.2.3.4/24" value="${value}">
            <button type="button" class="btn-link ${CLASS_NAMES.removeEssentialButton}">Удалить</button>
        </div>
    `;
}

function createInstanceRow(instance = {}) {
    const instanceId = getNextInstanceId();
    essentialCounters[instanceId] = 0;

    const shellConfig = instance.shellConfig || {};
    const useSSHChecked = shellConfig.useSSH ? 'checked' : '';
    const portValue = shellConfig.port ?? DEFAULT_PORT;
    const subnetPattern = instance.subnetPattern || DEFAULT_SUBNET_PATTERN;
    const essentialSubnets = (instance.essentialSubnets && instance.essentialSubnets.length)
        ? instance.essentialSubnets
        : [''];
    const shellSectionStyle = shellConfig.useSSH ? '' : 'display: none;';

    const essentialRows = essentialSubnets.map(value => createEssentialSubnetRow(instanceId, value)).join('');

    return `
        <div class="${CLASS_NAMES.instance}" data-instance-id="${instanceId}" style="border: 1px solid var(--color-border); padding: 20px; border-radius: 12px; margin-bottom: 20px; background: var(--color-surface, #1f2333);">
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
                <h4 style="margin: 0;">Инстанс</h4>
                <button type="button" class="btn-link ${CLASS_NAMES.removeInstanceButton}">Удалить</button>
            </div>
            <div class="form-group checkbox-group">
                <input type="checkbox" id="frr-use-ssh-${instanceId}" class="${CLASS_NAMES.shellUseSSH}" ${useSSHChecked}>
                <label for="frr-use-ssh-${instanceId}" style="margin-bottom: 0;">Использовать SSH</label>
            </div>
            <div class="${CLASS_NAMES.shellSection}" style="${shellSectionStyle}">
                <div class="form-group">
                    <label for="frr-host-${instanceId}">Хост</label>
                    <input type="text" id="frr-host-${instanceId}" class="form-control ${CLASS_NAMES.shellHost}" value="${shellConfig.host || ''}">
                </div>
                <div class="form-group">
                    <label for="frr-port-${instanceId}">Порт</label>
                    <input type="number" id="frr-port-${instanceId}" class="form-control ${CLASS_NAMES.shellPort}" value="${portValue}">
                </div>
                <div class="form-group">
                    <label for="frr-username-${instanceId}">Имя пользователя</label>
                    <input type="text" id="frr-username-${instanceId}" class="form-control ${CLASS_NAMES.shellUsername}" value="${shellConfig.username || ''}">
                </div>
                <div class="form-group">
                    <label for="frr-password-${instanceId}">Пароль</label>
                    <input type="password" id="frr-password-${instanceId}" class="form-control ${CLASS_NAMES.shellPassword}" placeholder="Оставьте пустым для сохранения текущего пароля" data-original-password="${shellConfig.password || ''}">
                </div>
            </div>
            <hr style="border: 0; border-top: 1px solid var(--color-border); margin: 20px 0;">
            <div class="form-group">
                <label for="frr-subnet-pattern-${instanceId}">Шаблон маршрута</label>
                <input type="text" id="frr-subnet-pattern-${instanceId}" class="form-control ${CLASS_NAMES.subnetPattern}" value="${subnetPattern}">
                <small class="hint-text">Используйте плейсхолдеры <code>{%subnet}</code> и <code>{%gateway}</code> для автоматической подстановки значений.</small>
            </div>
            <div class="form-group">
                <label for="frr-gateway-${instanceId}">Шлюз</label>
                <input type="text" id="frr-gateway-${instanceId}" class="form-control ${CLASS_NAMES.gateway}" placeholder="192.168.1.1" value="${instance.gateway || ''}">
            </div>
            <div class="form-group">
                <label>Обязательные подсети</label>
                <div class="${CLASS_NAMES.essentialList}" data-instance-id="${instanceId}">
                    ${essentialRows}
                </div>
                <button type="button" class="btn-secondary ${CLASS_NAMES.addEssentialButton}" data-instance-id="${instanceId}" style="margin-top: 10px;">Добавить подсеть</button>
                <small class="hint-text">Подсети должны быть указаны в формате IPv4 CIDR, например <code>10.0.0.0/24</code>.</small>
            </div>
        </div>
    `;
}

function populateInstances() {
    const instances = currentConfig.instances.length ? currentConfig.instances : [];
    const $list = $(SELECTORS.instancesList);
    resetCounters();
    $list.empty();
    instances.forEach(instance => {
        $list.append(createInstanceRow(instance));
    });
    updateAllShellFieldStates();
}

function renderFRRForm() {
    const $container = $(SELECTORS.container);
    $container.html(`
        <div class="component-config-form">
            <h3 class="config-section-title">Инстансы FRR</h3>
            <p class="hint-text" style="margin-bottom: 20px;">Настройте параметры подключения и маршрутизации для FRR. Можно добавить несколько инстансов.</p>
            <div id="${FIELD_IDS.instancesList}"></div>
            <div class="form-group" style="margin-top: 10px;">
                <button type="button" id="${FIELD_IDS.addInstanceButton}" class="btn-secondary" style="width: 220px;">Добавить инстанс</button>
            </div>
            <div class="action-buttons" style="margin-top: 40px;">
                <button id="${FIELD_IDS.saveButton}" class="btn-primary" style="width: 220px;">Применить Конфигурацию</button>
            </div>
            <div id="${FIELD_IDS.status}" class="error-message" style="display: none; margin-top: 20px;"></div>
        </div>
    `);

    populateInstances();
    attachEventHandlers();
}

function toggleShellFields($instance) {
    const enabled = $instance.find(`.${CLASS_NAMES.shellUseSSH}`).prop('checked');
    const $shellSection = $instance.find(`.${CLASS_NAMES.shellSection}`);
    $instance.find(`.${CLASS_NAMES.shellHost}`).prop('disabled', !enabled);
    $instance.find(`.${CLASS_NAMES.shellPort}`).prop('disabled', !enabled);
    $instance.find(`.${CLASS_NAMES.shellUsername}`).prop('disabled', !enabled);
    $instance.find(`.${CLASS_NAMES.shellPassword}`).prop('disabled', !enabled);
    $shellSection.toggle(enabled);
}

function updateAllShellFieldStates() {
    $(SELECTORS.instancesList).find(`.${CLASS_NAMES.instance}`).each((_, element) => {
        toggleShellFields($(element));
    });
}

function collectConfigFromForm() {
    const instances = [];

    $(SELECTORS.instancesList).find(`.${CLASS_NAMES.instance}`).each((_, element) => {
        const $instance = $(element);

        const useSSH = $instance.find(`.${CLASS_NAMES.shellUseSSH}`).prop('checked');
        const host = $instance.find(`.${CLASS_NAMES.shellHost}`).val().trim();
        const port = parseInt($instance.find(`.${CLASS_NAMES.shellPort}`).val(), 10) || DEFAULT_PORT;
        const username = $instance.find(`.${CLASS_NAMES.shellUsername}`).val().trim();
        const $passwordField = $instance.find(`.${CLASS_NAMES.shellPassword}`);
        const newPassword = $passwordField.val();
        const originalPassword = $passwordField.data('original-password') || '';
        const password = newPassword ? newPassword : originalPassword;

        const subnetPatternRaw = $instance.find(`.${CLASS_NAMES.subnetPattern}`).val().trim();
        const subnetPattern = subnetPatternRaw || DEFAULT_SUBNET_PATTERN;
        const gateway = $instance.find(`.${CLASS_NAMES.gateway}`).val().trim();

        const essentialSubnets = [];
        $instance.find(`.${CLASS_NAMES.essentialItem}`).each((_, itemElement) => {
            const value = $(itemElement).find(`.${CLASS_NAMES.essentialInput}`).val().trim();
            if (!value) {
                return;
            }
            if (!isValidIPv4Cidr(value)) {
                throw new Error(`Недопустимая подсеть: ${value}. Используйте формат IPv4 CIDR, например 10.0.0.0/24.`);
            }
            essentialSubnets.push(value);
        });

        instances.push({
            shellConfig: {
                useSSH,
                host,
                port,
                username,
                password
            },
            subnetPattern,
            gateway,
            essentialSubnets
        });
    });

    return { instances };
}

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

function handleAddInstance() {
    const $list = $(SELECTORS.instancesList);
    $list.append(createInstanceRow({
        shellConfig: {
            useSSH: false,
            host: '',
            port: DEFAULT_PORT,
            username: '',
            password: ''
        },
        subnetPattern: DEFAULT_SUBNET_PATTERN,
        gateway: '',
        essentialSubnets: ['']
    }));
    updateAllShellFieldStates();
}

function handleRemoveInstance(event) {
    event.preventDefault();
    $(event.currentTarget).closest(`.${CLASS_NAMES.instance}`).remove();
}

function handleToggleShellUseSSH(event) {
    const $instance = $(event.currentTarget).closest(`.${CLASS_NAMES.instance}`);
    toggleShellFields($instance);
}

function handleAddEssentialSubnet(event) {
    event.preventDefault();
    const $button = $(event.currentTarget);
    const $instance = $button.closest(`.${CLASS_NAMES.instance}`);
    const instanceId = $instance.data('instance-id');
    const $list = $instance.find(`.${CLASS_NAMES.essentialList}`);
    $list.append(createEssentialSubnetRow(instanceId, ''));
}

function handleRemoveEssentialSubnet(event) {
    event.preventDefault();
    $(event.currentTarget).closest(`.${CLASS_NAMES.essentialItem}`).remove();
}

async function handleSave() {
    const $button = $(SELECTORS.saveButton);
    clearStatus();

    let newConfig;
    try {
        newConfig = collectConfigFromForm();
    } catch (error) {
        console.error('Ошибка валидации конфига FRR:', error);
        updateStatus(error.message || 'Ошибка при подготовке конфигурации FRR.', 'error');
        return;
    }

    await runAction($button, 'Применение...', async () => {
        await JSONRPC.System.setComponentConfig(FRR_COMPONENT_NAME, newConfig);
        currentConfig = normalizeConfig(newConfig);
        populateInstances();
    }, {
        success: 'Конфигурация FRR успешно сохранена.',
        error: 'Ошибка при сохранении конфигурации FRR.',
        log: 'Ошибка сохранения конфига FRR'
    });
}

function attachEventHandlers() {
    $(SELECTORS.saveButton).off('click').on('click', handleSave);
    $(SELECTORS.addInstanceButton).off('click').on('click', handleAddInstance);
    $(SELECTORS.instancesList)
        .off('click', `.${CLASS_NAMES.removeInstanceButton}`).on('click', `.${CLASS_NAMES.removeInstanceButton}`, handleRemoveInstance)
        .off('change', `.${CLASS_NAMES.shellUseSSH}`).on('change', `.${CLASS_NAMES.shellUseSSH}`, handleToggleShellUseSSH)
        .off('click', `.${CLASS_NAMES.addEssentialButton}`).on('click', `.${CLASS_NAMES.addEssentialButton}`, handleAddEssentialSubnet)
        .off('click', `.${CLASS_NAMES.removeEssentialButton}`).on('click', `.${CLASS_NAMES.removeEssentialButton}`, handleRemoveEssentialSubnet);
}

function detachEventHandlers() {
    $(SELECTORS.saveButton).off('click');
    $(SELECTORS.addInstanceButton).off('click');
    $(SELECTORS.instancesList)
        .off('click', `.${CLASS_NAMES.removeInstanceButton}`)
        .off('change', `.${CLASS_NAMES.shellUseSSH}`)
        .off('click', `.${CLASS_NAMES.addEssentialButton}`)
        .off('click', `.${CLASS_NAMES.removeEssentialButton}`);
}

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