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

const FIELD_IDS = {
    container: 'unlock-site-container',
    form: 'unlock-site-form',
    domainInput: 'unlock-site-domain',
    serverInput: 'unlock-site-server',
    searchButton: 'unlock-site-search',
    results: 'unlock-site-results',
    status: 'unlock-site-status',
    addressesCheckbox: 'unlock-site-addresses-checkbox',
    subnetsCheckbox: 'unlock-site-subnets-checkbox',
    asnCheckbox: 'unlock-site-asn-checkbox',
    nameInput: 'unlock-site-name',
    storageSelect: 'unlock-site-storage',
    addButton: 'unlock-site-add-button',
    nameError: 'unlock-site-name-error',
    domainError: 'unlock-site-domain-error',
    serverError: 'unlock-site-server-error'
};

const SELECTORS = Object.entries(FIELD_IDS).reduce((acc, [key, value]) => {
    acc[key] = `#${value}`;
    return acc;
}, {});

const DEFAULT_DOMAIN = 'google.com';
const DEFAULT_SERVER = '8.8.8.8';

let currentResults = { addresses: [], subnets: [], ASN: [] };
let availableStorages = [];
let currentStorage = '';

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

function normalizeListing(values) {
    if (!Array.isArray(values)) {
        return [];
    }
    return values
        .map(item => (item === null || item === undefined) ? '' : String(item))
        .filter(item => item.length > 0);
}

async function loadLocalRepositories() {
    try {
        const repositories = await JSONRPC.SubscriptionManager.getLocalRepositories();
        return normalizeListing(repositories);
    } catch (error) {
        console.error('Ошибка получения списка хранилищ:', error);
        return [];
    }
}

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

function showFieldError(selector, message) {
    const $error = $(selector);
    if (!$error.length) {
        return;
    }
    $error.text(message || '').toggle(!!message);
}

function clearFieldError(selector) {
    showFieldError(selector, '');
}

function validateDomain(value) {
    const trimmed = value.trim();
    if (!trimmed) {
        return { valid: false, message: 'Укажите домен.' };
    }
    const domainPattern = /^(?=.{1,253}$)([A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,}$/;
    if (!domainPattern.test(trimmed)) {
        return { valid: false, message: 'Некорректный домен.' };
    }
    return { valid: true, message: '' };
}

function validateServer(value) {
    const trimmed = value.trim();
    if (!trimmed) {
        return { valid: false, message: 'Укажите DNS сервер.' };
    }
    const ipv4Pattern = /^(25[0-5]|2[0-4]\d|1?\d?\d)(\.(25[0-5]|2[0-4]\d|1?\d?\d)){3}$/;
    const domainPattern = /^(?=.{1,253}$)([A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\.)+[A-Za-z]{2,}$/;
    if (!ipv4Pattern.test(trimmed) && !domainPattern.test(trimmed)) {
        return { valid: false, message: 'Введите IP или домен DNS сервера.' };
    }
    return { valid: true, message: '' };
}

function validateListName(value) {
    const trimmed = value.trim();
    if (!trimmed) {
        return { valid: false, message: 'Имя списка не может быть пустым.' };
    }
    const namePattern = /^[A-Za-z0-9.]+$/;
    if (!namePattern.test(trimmed)) {
        return { valid: false, message: 'Допустимы только символы A-Z, a-z, 0-9 и точка.' };
    }
    return { valid: true, message: '' };
}

function buildListItems(items) {
    if (!items.length) {
        return '<div class="hint-text" style="margin-top: 12px;">Список пуст.</div>';
    }
    return `<div style="margin-top: 12px; display: flex; flex-direction: column; gap: 6px;">${items.map(item => `<div>${escapeHtml(item)}</div>`).join('')}</div>`;
}

function buildAsnItems(items) {
    if (!items.length) {
        return '<div class="hint-text" style="margin-top: 12px;">Список пуст.</div>';
    }
    return `<div style="margin-top: 12px;">${items.map(item => escapeHtml(item)).join(', ')}</div>`;
}

function renderResults(domainValue, storages) {
    const addresses = normalizeListing(currentResults.addresses);
    const subnets = normalizeListing(currentResults.subnets);
    const ASN = normalizeListing(currentResults.ASN);
    const storageOptions = Array.isArray(storages) ? storages : [];

    if (!storageOptions.includes(currentStorage)) {
        currentStorage = storageOptions.length ? storageOptions[0] : '';
    }

    const storageSelectDisabled = storageOptions.length === 0;
    const storageOptionsHtml = storageOptions.length
        ? storageOptions.map(storage => `<option value="${escapeHtml(storage)}"${storage === currentStorage ? ' selected' : ''}>${escapeHtml(storage)}</option>`).join('')
        : '<option value="">Нет доступных хранилищ</option>';
    const storageHint = storageOptions.length ? '' : '<div class="hint-text" style="margin-top: 8px;">Не найдено доступных хранилищ.</div>';

    const addressesDisabled = addresses.length === 0;
    const subnetsDisabled = subnets.length === 0;
    const asnDisabled = ASN.length === 0;

    const html = `
        <div style="margin-top: 24px; display: flex; flex-direction: column; gap: 16px;">
            <div class="card" style="padding: 20px;">
                <label style="display: flex; align-items: center; gap: 10px;">
                    <input type="checkbox" id="${FIELD_IDS.addressesCheckbox}" ${addressesDisabled ? 'disabled' : ''}>
                    <span>Добавить обнаруженные адреса</span>
                </label>
                ${buildListItems(addresses)}
            </div>
            <div class="card" style="padding: 20px;">
                <label style="display: flex; align-items: center; gap: 10px;">
                    <input type="checkbox" id="${FIELD_IDS.subnetsCheckbox}" ${subnetsDisabled ? 'disabled' : ''}>
                    <span>Добавить подсети, содержащие обнаруженные адреса</span>
                </label>
                ${buildListItems(subnets)}
            </div>
            <div class="card" style="padding: 20px;">
                <label style="display: flex; align-items: center; gap: 10px;">
                    <input type="checkbox" id="${FIELD_IDS.asnCheckbox}" ${asnDisabled ? 'disabled' : ''}>
                    <span>Добавить ASN, содержащие обнаруженные подсети</span>
                </label>
                ${buildAsnItems(ASN)}
            </div>
            <div class="form-group">
                <label for="${FIELD_IDS.storageSelect}">Хранилище</label>
                <select id="${FIELD_IDS.storageSelect}" class="form-control" ${storageSelectDisabled ? 'disabled' : ''}>
                    ${storageOptionsHtml}
                </select>
                ${storageHint}
            </div>
            <div class="form-group">
                <label for="${FIELD_IDS.nameInput}">Имя списка</label>
                <input type="text" id="${FIELD_IDS.nameInput}" class="form-control" value="${escapeHtml(domainValue)}">
                <div id="${FIELD_IDS.nameError}" class="error-message" style="display: none;"></div>
            </div>
            <div>
                <button type="button" id="${FIELD_IDS.addButton}" class="btn-primary" disabled>Добавить</button>
            </div>
        </div>
    `;

    const $results = $(SELECTORS.results);
    $results.html(html).show();
}

function updateAddButtonState() {
    const $addButton = $(SELECTORS.addButton);
    if (!$addButton.length) {
        return;
    }
    const $nameInput = $(SELECTORS.nameInput);
    const $storageSelect = $(SELECTORS.storageSelect);
    const { valid } = validateListName($nameInput.val() || '');
    const hasSelection = [
        $(SELECTORS.addressesCheckbox),
        $(SELECTORS.subnetsCheckbox),
        $(SELECTORS.asnCheckbox)
    ].some($checkbox => $checkbox.length && !$checkbox.prop('disabled') && $checkbox.prop('checked'));
    const storageValue = $storageSelect.length && !$storageSelect.prop('disabled') ? ($storageSelect.val() || '') : '';
    $addButton.prop('disabled', !(hasSelection && valid && storageValue.length > 0));
}

async function handleSearch(event) {
    event.preventDefault();
    setStatus('', '');
    const $domainInput = $(SELECTORS.domainInput);
    const $serverInput = $(SELECTORS.serverInput);

    const domainValidation = validateDomain($domainInput.val() || '');
    const serverValidation = validateServer($serverInput.val() || '');

    if (!domainValidation.valid) {
        showFieldError(SELECTORS.domainError, domainValidation.message);
    } else {
        clearFieldError(SELECTORS.domainError);
    }

    if (!serverValidation.valid) {
        showFieldError(SELECTORS.serverError, serverValidation.message);
    } else {
        clearFieldError(SELECTORS.serverError);
    }

    if (!domainValidation.valid || !serverValidation.valid) {
        return;
    }

    const $button = $(SELECTORS.searchButton);
    $button.prop('disabled', true).text('Поиск...');
    $(SELECTORS.results).hide().empty();

    try {
        const result = await JSONRPC.NetworkManager.discoverBlockedDomainResources(
            $domainInput.val().trim(),
            $serverInput.val().trim()
        );
        currentResults = {
            addresses: normalizeListing(result?.addresses),
            subnets: normalizeListing(result?.subnets),
            ASN: normalizeListing(result?.ASN)
        };
        availableStorages = await loadLocalRepositories();
        renderResults($domainInput.val().trim(), availableStorages);
        updateAddButtonState();
        clearFieldError(SELECTORS.nameError);
    } catch (error) {
        console.error('Ошибка поиска ресурсов домена:', error);
        currentResults = { addresses: [], subnets: [], ASN: [] };
        setStatus('Не удалось получить данные. Попробуйте позже.', 'error');
    } finally {
        $button.prop('disabled', false).text('Найти и разблокировать');
    }
}

function handleAdd() {
    const $nameInput = $(SELECTORS.nameInput);
    const validation = validateListName($nameInput.val() || '');
    if (!validation.valid) {
        showFieldError(SELECTORS.nameError, validation.message);
        updateAddButtonState();
        return;
    }
    showFieldError(SELECTORS.nameError, '');

    const $addButton = $(SELECTORS.addButton);
    $addButton.prop('disabled', true).text('Добавление...');
    setStatus('', '');

    const domain = ($(SELECTORS.domainInput).val() || '').trim();
    const selectedAddresses = $(SELECTORS.addressesCheckbox).prop('checked') ? currentResults.addresses : [];
    const selectedSubnets = $(SELECTORS.subnetsCheckbox).prop('checked') ? currentResults.subnets : [];
    const selectedAsn = $(SELECTORS.asnCheckbox).prop('checked') ? currentResults.ASN : [];
    const storage = $(SELECTORS.storageSelect).val() || '';

    if (!storage) {
        setStatus('Выберите хранилище.', 'error');
        $addButton.prop('disabled', false).text('Добавить');
        updateAddButtonState();
        return;
    }

    JSONRPC.SubscriptionManager.writeLocalResourceFile(
        $nameInput.val().trim(),
        "Unlocked resource: " + $nameInput.val().trim() + " (" + domain + ")",
        [domain],
        selectedAsn,
        selectedSubnets,
        selectedAddresses,
        storage,
        true
    ).then(() => {
        setStatus('Ресурсы успешно добавлены.', 'success');
    }).catch(error => {
        console.error('Ошибка добавления ресурсов:', error);
        setStatus('Не удалось добавить ресурсы.', 'error');
    }).finally(() => {
        $addButton.prop('disabled', false).text('Добавить');
        updateAddButtonState();
    });
}

function handleCheckboxChange() {
    updateAddButtonState();
}

function handleNameInputChange() {
    const $nameInput = $(SELECTORS.nameInput);
    const validation = validateListName($nameInput.val() || '');
    if (!validation.valid) {
        showFieldError(SELECTORS.nameError, validation.message);
    } else {
        clearFieldError(SELECTORS.nameError);
    }
    updateAddButtonState();
}

function handleStorageChange() {
    currentStorage = $(SELECTORS.storageSelect).val() || '';
    updateAddButtonState();
}

function attachEventHandlers() {
    $(SELECTORS.form).on('submit', handleSearch);
    $(SELECTORS.domainInput).on('input', () => clearFieldError(SELECTORS.domainError));
    $(SELECTORS.serverInput).on('input', () => clearFieldError(SELECTORS.serverError));
    $(SELECTORS.results).on('change', `input[type="checkbox"]`, handleCheckboxChange);
    $(SELECTORS.results).on('change', SELECTORS.storageSelect, handleStorageChange);
    $(SELECTORS.results).on('input', SELECTORS.nameInput, handleNameInputChange);
    $(SELECTORS.results).on('click', SELECTORS.addButton, handleAdd);
}

function detachEventHandlers() {
    $(SELECTORS.form).off('submit', handleSearch);
    $(SELECTORS.domainInput).off('input');
    $(SELECTORS.serverInput).off('input');
    $(SELECTORS.results).off('change');
    $(SELECTORS.results).off('input');
    $(SELECTORS.results).off('click');
}

function resetState() {
    currentResults = { addresses: [], subnets: [], ASN: [] };
    currentStorage = '';
    availableStorages = [];
    setStatus('', '');
}

export const UnlockSitePage = {
    render: () => `
        <div>
            <h1 class="page-title">Разблокировка сайта</h1>
            <div id="${FIELD_IDS.container}" class="card" style="padding: 24px; max-width: 640px; margin: 0 auto;">
                <form id="${FIELD_IDS.form}" style="display: flex; flex-direction: column; gap: 16px;">
                    <div class="form-group">
                        <label for="${FIELD_IDS.domainInput}">Домен</label>
                        <input type="text" id="${FIELD_IDS.domainInput}" class="form-control" value="${DEFAULT_DOMAIN}">
                        <div id="${FIELD_IDS.domainError}" class="error-message" style="display: none;"></div>
                    </div>
                    <div class="form-group">
                        <label for="${FIELD_IDS.serverInput}">Искать через DNS сервер</label>
                        <input type="text" id="${FIELD_IDS.serverInput}" class="form-control" value="${DEFAULT_SERVER}">
                        <div id="${FIELD_IDS.serverError}" class="error-message" style="display: none;"></div>
                    </div>
                    <div>
                        <button type="submit" id="${FIELD_IDS.searchButton}" class="btn-primary">Найти и разблокировать</button>
                    </div>
                </form>
                <div id="${FIELD_IDS.results}" style="display: none;"></div>
                <div id="${FIELD_IDS.status}" class="error-message" style="display: none; margin-top: 20px;"></div>
            </div>
        </div>
    `,
    mount: () => {
        attachEventHandlers();
    },
    unmount: () => {
        detachEventHandlers();
        resetState();
        $(SELECTORS.results).empty().hide();
    }
};
