import { useState, useEffect, useMemo } from 'react';
import api from './lib/api.js';
import { useNotify } from './components/NotifyProvider.jsx';
import FormModal from './components/FormModal.jsx';
import FormField from './components/FormField.jsx';
import ConfirmModal from './components/ConfirmModal.jsx';
import ServerAutocompleteInput from './components/ServerAutocompleteInput.jsx';
import GatewayAutocompleteInput from './components/GatewayAutocompleteInput.jsx';
import { countryToFlag } from './utils/serverUtils.js';
import {
  IconNetwork,
  IconPlus,
  IconEdit,
  IconTrash,
  IconDatabase,
  IconServer,
  IconWorld,
  IconRouter,
  IconCopy,
  IconSearch,
  IconRefresh,
  IconWand,
  IconSparkles,
  IconFilter,
  IconX,
  IconCircleFilled,
  IconLayoutGrid,
  IconList,
  IconCode,
  IconArrowsRightLeft,
  IconLock,
} from '@tabler/icons-react';

/**
 * Менеджер сетевых настроек
 * Справочник IP-адресов, интерфейсов и gateway для серверов
 */

// Типы провайдеров gateway
const GATEWAY_PROVIDERS = [
  { value: 'cloudflare', label: 'Cloudflare', color: 'orange' },
  { value: 'bunny', label: 'Bunny CDN', color: 'yellow' },
  { value: 'fastly', label: 'Fastly', color: 'red' },
  { value: 'telegram', label: 'Telegram', color: 'blue' },
  { value: 'hetzner', label: 'Hetzner', color: 'green' },
  { value: 'yandex', label: 'Yandex Cloud', color: 'cyan' },
  { value: 'custom', label: 'Другой', color: 'secondary' },
];

// Типы туннельных интерфейсов
const INTERFACE_TYPES = [
  { value: 'GRE', label: 'GRE', color: 'blue' },
  { value: 'WireGuard', label: 'WireGuard', color: 'green' },
  { value: 'IPSec', label: 'IPSec', color: 'yellow' },
  { value: 'VXLAN', label: 'VXLAN', color: 'purple' },
  { value: 'OpenVPN', label: 'OpenVPN', color: 'orange' },
];

// Типы gateway
const GATEWAY_TYPES = [
  { value: 'direct', label: 'Прямой', description: 'Прямой доступ в интернет', color: 'green' },
  { value: 'recursive', label: 'Рекурсивный', description: 'Ссылается на другой gateway', color: 'blue' },
];

// Пустые объекты
const getEmptyGateway = () => ({
  id: `gw-${Date.now()}-${Math.random().toString(16).slice(2, 6)}`,
  ip: '',
  description: '',
  serverId: '',
  country: '',
  type: 'direct',
  parentGateways: [], // Для рекурсивных - массив родительских gateway с distance [{id, distance}]
});

const getEmptyInterface = () => ({
  id: `if-${Date.now()}-${Math.random().toString(16).slice(2, 6)}`,
  name: '',
  name2: '', // Имя интерфейса на втором сервере (опционально)
  type: 'GRE',
  localIp: '',
  remoteIp: '',
  serverId: '',
  serverId2: '', // Второй сервер (опциональный)
  ipsecPasswordId: '', // ID IPSec пароля (опционально, только для IPSec)
  ipPoolId: '', // ID IP пула для выбора IP адресов (опционально)
  mtu: '', // MTU (опционально)
});

const getEmptyIpPool = () => ({
  id: `pool-${Date.now()}-${Math.random().toString(16).slice(2, 6)}`,
  name: '',
  cidr: '',
  description: '',
});

const getDefaultConfig = () => ({
  gateways: [],
  tunnelInterfaces: [],
  ipPools: [],
});

function NetworkConfigManager() {
  const notify = useNotify();
  
  // === Основные данные ===
  const [config, setConfig] = useState(getDefaultConfig());
  const [servers, setServers] = useState([]);
  const [loading, setLoading] = useState(false);
  const [saving, setSaving] = useState(false);
  
  // === UI State ===
  const [activeTab, setActiveTab] = useState('gateways');
  const [searchTerm, setSearchTerm] = useState('');
  const [providerFilter, setProviderFilter] = useState('');
  const [serverFilter, setServerFilter] = useState('');
  const [typeFilter, setTypeFilter] = useState('');
  const [gatewayTypeFilter, setGatewayTypeFilter] = useState(''); // Для фильтрации gateway по типу
  const [viewMode, setViewMode] = useState('cards'); // 'cards' | 'table'
  const [ipRegistrySearch, setIpRegistrySearch] = useState(''); // Поиск в реестре IP
  
  // === Modals ===
  const [gatewayModalOpen, setGatewayModalOpen] = useState(false);
  const [gatewayModalMode, setGatewayModalMode] = useState('add');
  const [editingGateway, setEditingGateway] = useState(null);
  
  const [interfaceModalOpen, setInterfaceModalOpen] = useState(false);
  const [interfaceModalMode, setInterfaceModalMode] = useState('add');
  const [editingInterface, setEditingInterface] = useState(null);
  
  const [poolModalOpen, setPoolModalOpen] = useState(false);
  const [poolModalMode, setPoolModalMode] = useState('add');
  const [editingPool, setEditingPool] = useState(null);
  
  const [deleteModalOpen, setDeleteModalOpen] = useState(false);
  const [itemToDelete, setItemToDelete] = useState(null);
  const [deleteType, setDeleteType] = useState('');
  
  // === Interface Template Modal ===
  const [interfaceTemplateModalOpen, setInterfaceTemplateModalOpen] = useState(false);
  const [templateServer1, setTemplateServer1] = useState('');
  const [templateServer2, setTemplateServer2] = useState('');
  const [templateType, setTemplateType] = useState('GRE');
  const [templateNamePrefix, setTemplateNamePrefix] = useState('');
  const [templateName1, setTemplateName1] = useState(''); // Опциональное имя для сервера 1
  const [templateName2, setTemplateName2] = useState(''); // Опциональное имя для сервера 2
  const [templateIpsecPasswordId, setTemplateIpsecPasswordId] = useState(''); // Выбранный IPSec пароль
  const [templateIpPoolId, setTemplateIpPoolId] = useState(''); // Выбранный IP пул
  const [templateMtu, setTemplateMtu] = useState(''); // MTU для шаблона
  const [templateTunnelCount, setTemplateTunnelCount] = useState(1); // Количество туннелей для создания
  const [templateServerPairs, setTemplateServerPairs] = useState([]); // Массив пар серверов для множественного создания
  
  // === IPSec Passwords Management ===
  const [ipsecPasswords, setIpsecPasswords] = useState([]);
  const [ipsecPasswordModalOpen, setIpsecPasswordModalOpen] = useState(false);
  const [ipsecPasswordsListModalOpen, setIpsecPasswordsListModalOpen] = useState(false);
  const [editingIpsecPassword, setEditingIpsecPassword] = useState(null);
  const [ipsecPasswordModalMode, setIpsecPasswordModalMode] = useState('add'); // 'add' | 'edit'
  
  // === MikroTik Code Generation ===
  const [mikrotikCodeModalOpen, setMikrotikCodeModalOpen] = useState(false);
  const [generatedMikrotikCode, setGeneratedMikrotikCode] = useState([]);

  // === Загрузка данных ===
  useEffect(() => {
    fetchConfig();
    fetchServers();
    fetchIpsecPasswords();
  }, []);

  const fetchConfig = async () => {
    setLoading(true);
    try {
      const response = await api.get('/network-config');
      const data = response.data || getDefaultConfig();
      
      // Миграция старых данных: преобразуем parentGatewayId в parentGateways
      const migratedGateways = (data.gateways || []).map(gw => {
        if (gw.type === 'recursive' && gw.parentGatewayId && (!gw.parentGateways || gw.parentGateways.length === 0)) {
          return {
            ...gw,
            parentGateways: [{ id: gw.parentGatewayId, distance: undefined }],
            parentGatewayId: undefined // Удаляем старое поле
          };
        }
        return gw;
      });
      
      setConfig({
        gateways: Array.isArray(migratedGateways) ? migratedGateways : [],
        tunnelInterfaces: Array.isArray(data.tunnelInterfaces) ? data.tunnelInterfaces : [],
        ipPools: Array.isArray(data.ipPools) ? data.ipPools : [],
      });
    } catch (error) {
      if (error.response?.status !== 404) {
        console.error('Error fetching network config:', error);
        notify.error('Не удалось загрузить сетевые настройки');
      }
      setConfig(getDefaultConfig());
    } finally {
      setLoading(false);
    }
  };

  const fetchServers = async () => {
    try {
      const response = await api.get('/servers');
      setServers(Array.isArray(response.data) ? response.data : []);
    } catch (error) {
      console.error('Error fetching servers:', error);
    }
  };

  const fetchIpsecPasswords = async () => {
    try {
      const response = await api.get('/ipsec-passwords');
      setIpsecPasswords(Array.isArray(response.data) ? response.data : []);
    } catch (error) {
      console.error('Error fetching IPSec passwords:', error);
      setIpsecPasswords([]);
    }
  };

  // === Сохранение ===
  const handleSave = async () => {
    setSaving(true);
    try {
      await api.post('/network-config', { domains: config });
      notify.success('Сетевые настройки сохранены');
    } catch (error) {
      console.error('Error saving network config:', error);
      notify.error('Не удалось сохранить настройки');
    } finally {
      setSaving(false);
    }
  };

  // === Получение информации о сервере ===
  const getServerInfo = (serverId) => {
    if (!serverId) return null;
    return servers.find(s => s.id === serverId || s.ip === serverId || s.dns === serverId);
  };

  const getServerLabel = (serverId) => {
    const server = getServerInfo(serverId);
    if (!server) return serverId || '—';
    return server.dns || server.ip;
  };

  // === Уникальные серверы для фильтра ===
  const uniqueServersInConfig = useMemo(() => {
    const allServerIds = new Set([
      ...(config.gateways || []).map(g => g.serverId).filter(Boolean),
      ...(config.tunnelInterfaces || []).map(i => i.serverId).filter(Boolean),
      ...(config.ipPools || []).map(p => p.serverId).filter(Boolean),
    ]);
    return Array.from(allServerIds).map(id => ({
      id,
      label: getServerLabel(id),
      server: getServerInfo(id),
    }));
  }, [config.gateways, config.tunnelInterfaces, config.ipPools, servers]);

  // === Фильтрация ===
  const filteredGateways = useMemo(() => {
    let result = [...(config.gateways || [])];
    
    if (providerFilter) {
      // Фильтруем по провайдеру сервера
      result = result.filter(g => {
        const server = getServerInfo(g.serverId);
        return server?.provider === providerFilter;
      });
    }
    
    if (serverFilter) {
      result = result.filter(g => g.serverId === serverFilter);
    }
    
    if (gatewayTypeFilter) {
      result = result.filter(g => g.type === gatewayTypeFilter);
    }
    
    if (searchTerm) {
      const term = searchTerm.toLowerCase();
      result = result.filter(g => {
        const server = getServerInfo(g.serverId);
        return (
          g.ip?.toLowerCase().includes(term) ||
          g.country?.toLowerCase().includes(term) ||
          server?.country?.toLowerCase().includes(term) ||
          server?.provider?.toLowerCase().includes(term) ||
          g.description?.toLowerCase().includes(term) ||
          getServerLabel(g.serverId).toLowerCase().includes(term)
        );
      });
    }
    
    return result;
  }, [config.gateways, providerFilter, serverFilter, typeFilter, searchTerm, servers]);

  const filteredInterfaces = useMemo(() => {
    let result = [...(config.tunnelInterfaces || [])];
    
    if (typeFilter) {
      result = result.filter(i => i.type === typeFilter);
    }
    
    if (serverFilter) {
      result = result.filter(i => i.serverId === serverFilter);
    }
    
    if (searchTerm) {
      const term = searchTerm.toLowerCase();
      result = result.filter(i =>
        i.name?.toLowerCase().includes(term) ||
        i.localIp?.toLowerCase().includes(term) ||
        i.remoteIp?.toLowerCase().includes(term) ||
        i.type?.toLowerCase().includes(term) ||
        getServerLabel(i.serverId).toLowerCase().includes(term)
      );
    }
    
    return result;
  }, [config.tunnelInterfaces, typeFilter, serverFilter, searchTerm, servers]);

  const filteredPools = useMemo(() => {
    let result = [...(config.ipPools || [])];
    
    if (serverFilter) {
      result = result.filter(p => p.serverId === serverFilter);
    }
    
    if (searchTerm) {
      const term = searchTerm.toLowerCase();
      result = result.filter(p => {
        const server = getServerInfo(p.serverId);
        return (
          p.name?.toLowerCase().includes(term) ||
          p.cidr?.toLowerCase().includes(term) ||
          p.description?.toLowerCase().includes(term) ||
          getServerLabel(p.serverId).toLowerCase().includes(term)
        );
      });
    }
    
    return result;
  }, [config.ipPools, serverFilter, searchTerm, servers]);

  // === Группировка по серверам ===
  const gatewaysByServer = useMemo(() => {
    const grouped = {};
    filteredGateways.forEach(gw => {
      const key = gw.serverId || '__unassigned__';
      if (!grouped[key]) grouped[key] = [];
      grouped[key].push(gw);
    });
    return grouped;
  }, [filteredGateways]);

  const interfacesByServer = useMemo(() => {
    const grouped = {};
    filteredInterfaces.forEach(iface => {
      // Группируем по первому серверу
      const key1 = iface.serverId || '__unassigned__';
      if (!grouped[key1]) grouped[key1] = [];
      grouped[key1].push(iface);
      
      // Если есть второй сервер, также добавляем в его группу
      if (iface.serverId2) {
        const key2 = iface.serverId2;
        if (!grouped[key2]) grouped[key2] = [];
        grouped[key2].push(iface);
      }
    });
    return grouped;
  }, [filteredInterfaces]);

  // === Сброс фильтров ===
  const resetFilters = () => {
    setSearchTerm('');
    setProviderFilter('');
    setServerFilter('');
    setTypeFilter('');
    setGatewayTypeFilter('');
  };

  const hasActiveFilters = searchTerm || providerFilter || serverFilter || typeFilter || gatewayTypeFilter;

  // === CRUD для Gateways ===
  const handleAddGateway = () => {
    setEditingGateway(getEmptyGateway());
    setGatewayModalMode('add');
    setGatewayModalOpen(true);
  };

  const handleEditGateway = (gateway) => {
    // Миграция старых данных при редактировании
    const migratedGateway = gateway.type === 'recursive' && gateway.parentGatewayId && (!gateway.parentGateways || gateway.parentGateways.length === 0)
      ? {
          ...gateway,
          parentGateways: [{ id: gateway.parentGatewayId, distance: undefined }]
        }
      : {
          ...gateway,
          parentGateways: gateway.parentGateways || []
        };
    setEditingGateway(migratedGateway);
    setGatewayModalMode('edit');
    setGatewayModalOpen(true);
  };

  const handleSaveGateway = (gatewayData) => {
    // Валидация: IP адрес обязателен
    if (!gatewayData.ip || !gatewayData.ip.trim()) {
      notify.error('IP адрес обязателен');
      return;
    }
    
    // Очищаем пустые parentGateways и удаляем старое поле parentGatewayId
    const cleanedData = {
      ...gatewayData,
      parentGateways: gatewayData.type === 'recursive' 
        ? (gatewayData.parentGateways || []).filter(p => p && p.id)
        : [],
      parentGatewayId: undefined // Удаляем старое поле
    };
    
    if (gatewayModalMode === 'add') {
      // Проверка на дубликат IP
      const existingGateway = config.gateways.find(g => g.ip === cleanedData.ip.trim());
      if (existingGateway) {
        notify.error(`Gateway с IP ${cleanedData.ip} уже существует`);
        return;
      }
      setConfig(prev => ({
        ...prev,
        gateways: [...prev.gateways, cleanedData],
      }));
      notify.success('Gateway добавлен');
    } else {
      // При редактировании ищем по ID, но проверяем, не занят ли новый IP другим gateway
      const currentGateway = config.gateways.find(g => g.id === cleanedData.id);
      if (!currentGateway) {
        notify.error('Gateway не найден');
        return;
      }
      
      // Если IP изменился, проверяем, не занят ли он другим gateway
      if (cleanedData.ip.trim() !== currentGateway.ip && 
          config.gateways.some(g => g.id !== cleanedData.id && g.ip === cleanedData.ip.trim())) {
        notify.error(`Gateway с IP ${cleanedData.ip} уже существует`);
        return;
      }
      
      setConfig(prev => ({
        ...prev,
        gateways: prev.gateways.map(g => g.id === cleanedData.id ? cleanedData : g),
      }));
      notify.success('Gateway обновлён');
    }
    setGatewayModalOpen(false);
    setEditingGateway(null);
  };

  const handleDeleteGateway = (gateway) => {
    setItemToDelete(gateway);
    setDeleteType('gateway');
    setDeleteModalOpen(true);
  };

  // === Генерация имени интерфейса на основе серверов ===
  // Для сервера 1: берем часть из DNS сервера 2 (например, msk) и имя хоста сервера 2 (ihor)
  // Для сервера 2: берем часть из DNS сервера 1 (например, swe) и имя хоста сервера 1 (hiphost)
  const generateInterfaceName = (currentServer, otherServer, type, prefix = '') => {
    // Парсим DNS имена
    const parseDnsParts = (dns) => {
      if (!dns) return null;
      const parts = dns.split('.');
      if (parts.length >= 2) {
        return {
          hostname: parts[0], // первая часть (имя хоста)
          location: parts[1]  // вторая часть (локация, например msk, swe)
        };
      }
      return null;
    };
    
    const currentParts = parseDnsParts(currentServer?.dns);
    const otherParts = parseDnsParts(otherServer?.dns);
    
    let name;
    
    if (currentParts && otherParts) {
      // Используем локацию из другого сервера и имя хоста из другого сервера
      // Например: для сервера 1 (hiphost.swe.shx.su) с сервером 2 (ihor.msk.rt.shx.su)
      // Имя на сервере 1: msk-ihor
      name = `${otherParts.location}-${otherParts.hostname}`;
    } else if (currentServer?.dns) {
      // Fallback: используем первую часть DNS
      name = currentServer.dns.split('.')[0];
    } else if (currentServer?.ip) {
      // Fallback: используем IP
      name = currentServer.ip.split('.').join('-');
    } else {
      name = 'server';
    }
    
    const prefixPart = prefix ? `${prefix}-` : '';
    return `${prefixPart}${name}`.toUpperCase();
  };

  // === Создание интерфейса из шаблона ===
  const handleCreateInterfaceFromTemplate = () => {
    const tunnelCount = Math.max(1, Math.min(100, parseInt(templateTunnelCount) || 1)); // Ограничиваем от 1 до 100
    
    // Если количество туннелей больше 1, используем выбранные пары серверов
    if (tunnelCount > 1) {
      // Проверяем, что все пары заполнены
      if (templateServerPairs.length !== tunnelCount) {
        notify.error(`Необходимо настроить ${tunnelCount} пар серверов`);
        return;
      }
      
      const invalidPairs = templateServerPairs.filter((pair, index) => {
        if (!pair.server1 || !pair.server2) {
          return true;
        }
        if (pair.server1 === pair.server2) {
          return true;
        }
        return false;
      });
      
      if (invalidPairs.length > 0) {
        notify.error('Не все пары серверов настроены корректно. Проверьте, что выбраны разные серверы для каждой пары.');
        return;
      }
      
      const newInterfaces = [];
      const usedIps = new Set(getAllUsedIpsSet); // Создаем Set с уже использованными IP из существующих интерфейсов
      
      // Создаем туннели для каждой пары
      templateServerPairs.forEach((pair, index) => {
        const server1 = getServerInfo(pair.server1);
        const server2 = getServerInfo(pair.server2);
        
        if (!server1 || !server2) {
          notify.error(`Не удалось найти информацию о серверах для пары ${index + 1}`);
          return;
        }
        
        // Генерируем имена интерфейсов
        const baseName1 = generateInterfaceName(server1, server2, templateType, templateNamePrefix);
        const baseName2 = generateInterfaceName(server2, server1, templateType, templateNamePrefix);
        const name1 = (pair.name1?.trim() || baseName1).toUpperCase();
        const name2 = (pair.name2?.trim() || baseName2).toUpperCase();
        
        // Используем настройки из пары или глобальные для MTU
        const pairMtu = pair.mtu || templateMtu;
        
        // Используем настройки из пары или глобальные
        const pairIpsecPasswordId = pair.ipsecPasswordId || templateIpsecPasswordId;
        const pairIpPoolId = pair.ipPoolId || templateIpPoolId;
        
        // Генерируем IP адреса (учитываем уже использованные в этой итерации)
        // Важно: Local IP и Remote IP должны быть разными и в одной сети /30
        // Передаем usedIps в функцию, чтобы она учитывала IP, выделенные для предыдущих туннелей
        let localIp = null;
        let remoteIp = null;
        let attempts = 0;
        const maxAttempts = 1000;
        
        while ((!localIp || !remoteIp || localIp === remoteIp) && attempts < maxAttempts) {
          const candidateLocal = generateFreePrivateIp(null, false, null, pairIpPoolId || null, usedIps);
          if (candidateLocal && !usedIps.has(candidateLocal)) {
            const candidateRemote = generateFreePrivateIp(null, true, candidateLocal, pairIpPoolId || null, usedIps);
            if (candidateRemote && !usedIps.has(candidateRemote) && candidateRemote !== candidateLocal) {
              localIp = candidateLocal;
              remoteIp = candidateRemote;
              usedIps.add(localIp);
              usedIps.add(remoteIp);
              break;
            }
          }
          attempts++;
        }
        
        if (!localIp || !remoteIp || localIp === remoteIp) {
          notify.error(`Не удалось найти свободные IP адреса для туннеля ${index + 1} (${server1.dns || server1.ip} ↔ ${server2.dns || server2.ip}). Возможно, в пуле закончились свободные адреса.`);
          return;
        }
        
        // Создаем интерфейс
        const newInterface = {
          ...getEmptyInterface(),
          name: name1,
          name2: name2,
          type: templateType,
          localIp: localIp,
          remoteIp: remoteIp,
          serverId: pair.server1,
          serverId2: pair.server2,
          ipsecPasswordId: (templateType === 'IPSec' || templateType === 'GRE') && pairIpsecPasswordId ? pairIpsecPasswordId : '',
          ipPoolId: pairIpPoolId || '',
          mtu: pairMtu || ''
        };
        
        // Проверяем конфликты с существующими интерфейсами
        const conflicts = checkInterfaceIpConflict(newInterface);
        if (conflicts.length > 0) {
          notify.error(`Обнаружены конфликты IP адресов для туннеля ${index + 1}. Попробуйте еще раз.`);
          return;
        }
        
        newInterfaces.push(newInterface);
      });
      
      if (newInterfaces.length === 0) {
        return; // Ошибки уже показаны выше
      }
      
      // Добавляем все созданные интерфейсы
      setConfig(prev => ({
        ...prev,
        tunnelInterfaces: [...prev.tunnelInterfaces, ...newInterfaces],
      }));
      
      notify.success(`Создано туннелей: ${newInterfaces.length}`);
      
      // Закрываем модал и сбрасываем значения
      setInterfaceTemplateModalOpen(false);
      setTemplateServer1('');
      setTemplateServer2('');
      setTemplateType('GRE');
      setTemplateNamePrefix('');
      setTemplateName1('');
      setTemplateName2('');
      setTemplateIpsecPasswordId('');
      setTemplateIpPoolId('');
      setTemplateMtu('');
      setTemplateTunnelCount(1);
      setTemplateServerPairs([]);
      return;
    }
    
    // Если количество туннелей = 1, используем старую логику с выбором двух серверов
    if (!templateServer1 || !templateServer2) {
      notify.error('Выберите оба сервера');
      return;
    }
    
    if (templateServer1 === templateServer2) {
      notify.error('Серверы должны быть разными');
      return;
    }
    
    const server1 = getServerInfo(templateServer1);
    const server2 = getServerInfo(templateServer2);
    
    if (!server1 || !server2) {
      notify.error('Не удалось найти информацию о серверах');
      return;
    }
    
    // Генерируем имена интерфейсов (используем опциональные имена если указаны)
    const name1 = (templateName1.trim() || generateInterfaceName(server1, server2, templateType, templateNamePrefix)).toUpperCase();
    const name2 = (templateName2.trim() || generateInterfaceName(server2, server1, templateType, templateNamePrefix)).toUpperCase();
    
    // Генерируем IP адреса
    const localIp = generateFreePrivateIp(null, false, null, templateIpPoolId || null);
    if (!localIp) {
      notify.error('Не удалось найти свободный Local IP адрес');
      return;
    }
    
    const remoteIp = generateFreePrivateIp(null, true, localIp, templateIpPoolId || null);
    if (!remoteIp || remoteIp === localIp) {
      notify.error('Не удалось найти свободный Remote IP адрес (отличающийся от Local IP)');
      return;
    }
    
    // Проверяем конфликты
    const newInterface = {
      ...getEmptyInterface(),
      name: name1,
      name2: name2,
      type: templateType,
      localIp: localIp,
      remoteIp: remoteIp,
      serverId: templateServer1,
      serverId2: templateServer2,
      ipsecPasswordId: (templateType === 'IPSec' || templateType === 'GRE') && templateIpsecPasswordId ? templateIpsecPasswordId : '',
      ipPoolId: templateIpPoolId || '',
      mtu: templateMtu || ''
    };
    
    const conflicts = checkInterfaceIpConflict(newInterface);
    if (conflicts.length > 0) {
      notify.error('Обнаружены конфликты IP адресов. Попробуйте еще раз.');
      return;
    }
    
    // Создаем интерфейс
    setConfig(prev => ({
      ...prev,
      tunnelInterfaces: [...prev.tunnelInterfaces, newInterface],
    }));
    
    notify.success(`Интерфейс создан: ${name1} (${localIp} ↔ ${remoteIp})`);
    
    // Закрываем модал и сбрасываем значения
    setInterfaceTemplateModalOpen(false);
    setTemplateServer1('');
    setTemplateServer2('');
    setTemplateType('GRE');
    setTemplateNamePrefix('');
    setTemplateName1('');
    setTemplateName2('');
    setTemplateIpsecPasswordId('');
    setTemplateIpPoolId('');
    setTemplateMtu('');
    setTemplateTunnelCount(1);
  };

  // === CRUD для Interfaces ===
  const handleAddInterface = () => {
    setEditingInterface(getEmptyInterface());
    setInterfaceModalMode('add');
    setInterfaceModalOpen(true);
  };

  const handleEditInterface = (iface) => {
    setEditingInterface({ ...iface });
    setInterfaceModalMode('edit');
    setInterfaceModalOpen(true);
  };

  // === Проверка пересечений IP адресов для интерфейсов ===
  const checkInterfaceIpConflict = (ifaceData, excludeId = null) => {
    const conflicts = [];
    const allInterfaces = config.tunnelInterfaces || [];
    
    // Проверяем localIp
    if (ifaceData.localIp && ifaceData.localIp.trim()) {
      const conflictingLocal = allInterfaces.find(i => 
        i.id !== excludeId && 
        (i.localIp === ifaceData.localIp.trim() || i.remoteIp === ifaceData.localIp.trim())
      );
      if (conflictingLocal) {
        conflicts.push({
          ip: ifaceData.localIp.trim(),
          type: 'localIp',
          conflictingInterface: conflictingLocal
        });
      }
    }
    
    // Проверяем remoteIp
    if (ifaceData.remoteIp && ifaceData.remoteIp.trim()) {
      const conflictingRemote = allInterfaces.find(i => 
        i.id !== excludeId && 
        (i.localIp === ifaceData.remoteIp.trim() || i.remoteIp === ifaceData.remoteIp.trim())
      );
      if (conflictingRemote) {
        conflicts.push({
          ip: ifaceData.remoteIp.trim(),
          type: 'remoteIp',
          conflictingInterface: conflictingRemote
        });
      }
    }
    
    return conflicts;
  };

  // === Получение множества всех используемых IP адресов ===
  const getAllUsedIpsSet = useMemo(() => {
    const usedIps = new Set();
    (config.tunnelInterfaces || []).forEach(iface => {
      if (iface.localIp && iface.localIp.trim()) {
        usedIps.add(iface.localIp.trim());
      }
      if (iface.remoteIp && iface.remoteIp.trim()) {
        usedIps.add(iface.remoteIp.trim());
      }
    });
    return usedIps;
  }, [config.tunnelInterfaces]);

  // === Генерация свободного IP адреса из приватных диапазонов ===
  // Генерирует IP в сетях /30 (четные базовые адреса)
  // Если указан ipPoolId, использует IP пул, иначе использует приватные диапазоны RFC 1918
  // usedIpsOverride - опциональный Set уже использованных IP (если не передан, создается копия getAllUsedIpsSet)
  const generateFreePrivateIp = (excludeIp = null, forRemote = false, pairedLocalIp = null, ipPoolId = null, usedIpsOverride = null) => {
    // Создаем копию Set, чтобы не модифицировать оригинальный
    const usedIps = usedIpsOverride || new Set(getAllUsedIpsSet);
    if (excludeIp) {
      usedIps.delete(excludeIp.trim());
    }

    // Если указан IP пул, используем его
    if (ipPoolId) {
      const pool = (config.ipPools || []).find(p => p.id === ipPoolId);
      if (pool && pool.cidr) {
        return generateIpFromPool(pool.cidr, usedIps, excludeIp, forRemote, pairedLocalIp);
      }
    }

    // Если подбираем Remote IP и есть Local IP, генерируем парный IP в той же сети /30
    if (forRemote && pairedLocalIp) {
      const localIpParts = pairedLocalIp.trim().split('.');
      if (localIpParts.length === 4) {
        const baseOctet = parseInt(localIpParts[3]);
        // Определяем базовый адрес сети /30 (округляем вниз до кратного 4)
        const networkBase = Math.floor(baseOctet / 4) * 4;
        const localOffset = baseOctet - networkBase;
        
        // Если Local IP уже .1, то Remote должен быть .2
        // Если Local IP .2, то Remote должен быть .1
        let remoteOffset;
        if (localOffset === 1) {
          remoteOffset = 2;
        } else if (localOffset === 2) {
          remoteOffset = 1;
        } else {
          // Если Local IP не .1 или .2, используем стандартную логику
          remoteOffset = localOffset === 0 ? 2 : (localOffset === 3 ? 1 : 2);
        }
        
        const remoteOctet = networkBase + remoteOffset;
        if (remoteOctet >= 0 && remoteOctet <= 255) {
          const remoteIp = `${localIpParts[0]}.${localIpParts[1]}.${localIpParts[2]}.${remoteOctet}`;
          if (!usedIps.has(remoteIp)) {
            return remoteIp;
          }
        }
      }
    }

    // Приватные диапазоны для туннелей (RFC 1918)
    // Генерируем пары IP в сетях /30 (базовый адрес кратен 4)
    const ranges = [
      { start: [10, 10, 0, 0], end: [10, 10, 255, 252] }, // 10.10.0.0/16
      { start: [10, 0, 0, 0], end: [10, 255, 255, 252] }, // 10.0.0.0/8
      { start: [172, 16, 0, 0], end: [172, 31, 255, 252] }, // 172.16.0.0/12
      { start: [192, 168, 0, 0], end: [192, 168, 255, 252] }, // 192.168.0.0/16
    ];

    for (const range of ranges) {
      const [a, b, c, d] = range.start;
      const [aEnd, bEnd, cEnd, dEnd] = range.end;
      
      // Перебираем IP в диапазоне с шагом 4 (сети /30)
      for (let aVal = a; aVal <= aEnd; aVal++) {
        const bStart = (aVal === a) ? b : 0;
        const bEndVal = (aVal === aEnd) ? bEnd : 255;
        for (let bVal = bStart; bVal <= bEndVal; bVal++) {
          const cStart = (aVal === a && bVal === b) ? c : 0;
          const cEndVal = (aVal === aEnd && bVal === bEnd) ? cEnd : 255;
          for (let cVal = cStart; cVal <= cEndVal; cVal++) {
            const dStart = (aVal === a && bVal === b && cVal === c) ? d : 0;
            const dEndVal = (aVal === aEnd && bVal === bEnd && cVal === cEnd) ? dEnd : 252;
            // Перебираем только базовые адреса сетей /30 (кратные 4)
            for (let dVal = dStart; dVal <= dEndVal; dVal += 4) {
              // Local IP = базовый + 1, Remote IP = базовый + 2
              const localIp = `${aVal}.${bVal}.${cVal}.${dVal + 1}`;
              const remoteIp = `${aVal}.${bVal}.${cVal}.${dVal + 2}`;
              
              // Проверяем, свободны ли оба IP
              if (!usedIps.has(localIp) && !usedIps.has(remoteIp)) {
                return forRemote ? remoteIp : localIp;
              }
            }
          }
        }
      }
    }

    // Если все IP заняты, возвращаем null
    return null;
  };

  // === Генерация IP из пула ===
  const generateIpFromPool = (cidr, usedIps, excludeIp = null, forRemote = false, pairedLocalIp = null) => {
    // Парсим CIDR (например, "10.10.0.0/24")
    const [network, prefixLength] = cidr.split('/');
    if (!network || !prefixLength) {
      return null;
    }
    
    const prefix = parseInt(prefixLength);
    if (isNaN(prefix) || prefix < 0 || prefix > 32) {
      return null;
    }
    
    const networkParts = network.split('.');
    if (networkParts.length !== 4) {
      return null;
    }
    
    const [a, b, c, d] = networkParts.map(Number);
    if (networkParts.some(p => isNaN(Number(p)))) {
      return null;
    }
    
    // Если подбираем Remote IP и есть Local IP, генерируем парный IP в той же сети /30
    if (forRemote && pairedLocalIp) {
      const localIpParts = pairedLocalIp.trim().split('.');
      if (localIpParts.length === 4) {
        // Проверяем, что Local IP входит в пул
        if (!isIpInCidr(pairedLocalIp, cidr)) {
          return null; // Local IP не в пуле, не можем сгенерировать Remote
        }
        
        const baseOctet = parseInt(localIpParts[3]);
        const networkBase = Math.floor(baseOctet / 4) * 4;
        const localOffset = baseOctet - networkBase;
        
        let remoteOffset;
        if (localOffset === 1) {
          remoteOffset = 2;
        } else if (localOffset === 2) {
          remoteOffset = 1;
        } else {
          remoteOffset = localOffset === 0 ? 2 : (localOffset === 3 ? 1 : 2);
        }
        
        const remoteOctet = networkBase + remoteOffset;
        if (remoteOctet >= 0 && remoteOctet <= 255) {
          const remoteIp = `${localIpParts[0]}.${localIpParts[1]}.${localIpParts[2]}.${remoteOctet}`;
          // Проверяем, что Remote IP входит в диапазон пула и отличается от Local IP
          if (isIpInCidr(remoteIp, cidr) && !usedIps.has(remoteIp) && remoteIp !== pairedLocalIp) {
            return remoteIp;
          }
        }
      }
      // Если не удалось сгенерировать парный Remote IP, продолжаем поиск в общем цикле ниже
      // Не возвращаем null сразу, чтобы попробовать найти другую пару
    }
    
    // Вычисляем количество хостов в сети
    const hostBits = 32 - prefix;
    
    // Для /30 сетей используем шаг 4 (базовые адреса кратные 4)
    const step = prefix >= 30 ? 4 : 1;
    
    // Определяем диапазон для перебора в зависимости от префикса
    if (prefix >= 24) {
      // /24 - /32: меняем только последний октет
      const startOctet = d;
      const maxHosts = Math.pow(2, hostBits);
      const endOctet = Math.min(d + maxHosts - 1, 255);
      
      // Перебираем IP в диапазоне
      for (let dVal = startOctet; dVal <= endOctet; dVal += step) {
        if (prefix >= 30 && dVal % 4 !== 0) continue; // Для /30 только кратные 4
        
        // Local IP = базовый + 1, Remote IP = базовый + 2
        const localIp = `${a}.${b}.${c}.${dVal + 1}`;
        const remoteIp = `${a}.${b}.${c}.${dVal + 2}`;
        
        // Проверяем, что IP входят в диапазон пула
        if (!isIpInCidr(localIp, cidr)) continue;
        if (!isIpInCidr(remoteIp, cidr)) continue;
        
        // Проверяем, что IP отличаются друг от друга
        if (localIp === remoteIp) continue;
        
        // Для всех префиксов проверяем, что оба IP свободны (для туннелей нужны пары)
        if (!usedIps.has(localIp) && !usedIps.has(remoteIp)) {
          return forRemote ? remoteIp : localIp;
        }
      }
    } else if (prefix >= 16) {
      // /16 - /23: меняем третий и четвертый октеты
      const thirdOctetRange = Math.pow(2, Math.max(0, 24 - prefix));
      for (let cVal = c; cVal < c + thirdOctetRange && cVal <= 255; cVal++) {
        const dStart = (cVal === c) ? d : 0;
        const dEnd = 255;
        for (let dVal = dStart; dVal <= dEnd; dVal += step) {
          if (prefix >= 30 && dVal % 4 !== 0) continue; // Для /30 только кратные 4
          const localIp = `${a}.${b}.${cVal}.${dVal + 1}`; // Local IP = базовый + 1
          const remoteIp = `${a}.${b}.${cVal}.${dVal + 2}`; // Remote IP = базовый + 2
          
          // Проверяем, что IP входят в диапазон пула и отличаются
          if (!isIpInCidr(localIp, cidr)) continue;
          if (localIp === remoteIp) continue;
          
          // Проверяем, что Remote IP тоже входит в пул
          if (!isIpInCidr(remoteIp, cidr)) continue;
          
          // Для всех префиксов проверяем, что оба IP свободны (для туннелей нужны пары)
          if (!usedIps.has(localIp) && !usedIps.has(remoteIp)) {
            return forRemote ? remoteIp : localIp;
          }
        }
      }
    } else {
      // /0 - /15: слишком большой диапазон, используем упрощенную логику
      return null;
    }
    
    return null;
  };

  // === Проверка, входит ли IP в CIDR ===
  const isIpInCidr = (ip, cidr) => {
    const [network, prefixLength] = cidr.split('/');
    if (!network || !prefixLength) return false;
    
    const prefix = parseInt(prefixLength);
    if (isNaN(prefix)) return false;
    
    const networkParts = network.split('.').map(Number);
    const ipParts = ip.split('.').map(Number);
    
    if (networkParts.length !== 4 || ipParts.length !== 4) return false;
    
    // Вычисляем маску сети
    const mask = (0xFFFFFFFF << (32 - prefix)) >>> 0;
    
    // Преобразуем IP в число
    const networkNum = (networkParts[0] << 24) | (networkParts[1] << 16) | (networkParts[2] << 8) | networkParts[3];
    const ipNum = (ipParts[0] << 24) | (ipParts[1] << 16) | (ipParts[2] << 8) | ipParts[3];
    
    return (networkNum & mask) === (ipNum & mask);
  };

  // === Подбор IP для интерфейса ===
  const handleSuggestLocalIp = () => {
    const ipPoolId = editingInterface?.ipPoolId || null;
    const freeIp = generateFreePrivateIp(editingInterface?.localIp, false, null, ipPoolId);
    if (freeIp) {
      setEditingInterface({ ...editingInterface, localIp: freeIp });
      notify.success(`Подобран Local IP: ${freeIp}`);
    } else {
      notify.error('Не удалось найти свободный IP адрес');
    }
  };

  const handleSuggestRemoteIp = () => {
    // Если есть Local IP, генерируем парный Remote IP в той же сети /30
    const ipPoolId = editingInterface?.ipPoolId || null;
    const freeIp = generateFreePrivateIp(
      editingInterface?.remoteIp, 
      true, 
      editingInterface?.localIp || null,
      ipPoolId
    );
    if (freeIp) {
      setEditingInterface({ ...editingInterface, remoteIp: freeIp });
      notify.success(`Подобран Remote IP: ${freeIp}`);
    } else {
      notify.error('Не удалось найти свободный IP адрес');
    }
  };

  // === Получение реестра всех используемых IP адресов ===
  const ipRegistry = useMemo(() => {
    const registry = [];
    
    // Собираем IP из интерфейсов - каждая запись это отдельное использование IP
    (config.tunnelInterfaces || []).forEach(iface => {
      if (iface.localIp && iface.localIp.trim()) {
        const server = getServerInfo(iface.serverId);
        registry.push({
          ip: iface.localIp.trim(),
          type: 'localIp',
          interface: iface,
          interfaceName: iface.name || iface.id,
          server: server, // localIp привязан к serverId
          serverName: server?.dns || server?.ip || iface.serverId || '—',
          ptrZone: server?.dns || '—' // PTR зона = доменное имя сервера
        });
      }
      if (iface.remoteIp && iface.remoteIp.trim()) {
        const server2 = getServerInfo(iface.serverId2);
        registry.push({
          ip: iface.remoteIp.trim(),
          type: 'remoteIp',
          interface: iface,
          interfaceName: iface.name || iface.id,
          server: server2, // remoteIp привязан к serverId2
          serverName: server2?.dns || server2?.ip || iface.serverId2 || '—',
          ptrZone: server2?.dns || '—' // PTR зона = доменное имя сервера
        });
      }
    });
    
    // Проверяем конфликты (один IP используется в нескольких интерфейсах)
    const ipUsageMap = {};
    registry.forEach(item => {
      if (!ipUsageMap[item.ip]) {
        ipUsageMap[item.ip] = [];
      }
      ipUsageMap[item.ip].push(item);
    });
    
    // Добавляем флаг конфликта
    return registry.map(item => ({
      ...item,
      hasConflict: ipUsageMap[item.ip].length > 1
    })).sort((a, b) => {
      // Сначала конфликты, потом по IP, потом по типу
      if (a.hasConflict !== b.hasConflict) {
        return a.hasConflict ? -1 : 1;
      }
      if (a.ip !== b.ip) {
        return a.ip.localeCompare(b.ip);
      }
      return a.type.localeCompare(b.type);
    });
  }, [config.tunnelInterfaces, servers]);

  // === Фильтрация реестра IP ===
  const filteredIpRegistry = useMemo(() => {
    if (!ipRegistrySearch) return ipRegistry;
    const term = ipRegistrySearch.toLowerCase();
    return ipRegistry.filter(item => 
      item.ip.toLowerCase().includes(term) ||
      item.interfaceName.toLowerCase().includes(term) ||
      item.serverName.toLowerCase().includes(term)
    );
  }, [ipRegistry, ipRegistrySearch]);

  const handleSaveInterface = (ifaceData) => {
    // Преобразуем имена интерфейсов в верхний регистр
    const normalizedData = {
      ...ifaceData,
      name: ifaceData.name ? ifaceData.name.toUpperCase() : '',
      name2: ifaceData.name2 ? ifaceData.name2.toUpperCase() : '',
    };
    
    // Валидация: проверка пересечений IP адресов
    const conflicts = checkInterfaceIpConflict(
      normalizedData, 
      interfaceModalMode === 'edit' ? normalizedData.id : null
    );
    
    if (conflicts.length > 0) {
      const conflictMessages = conflicts.map(c => {
        const conflictName = c.conflictingInterface.name || c.conflictingInterface.id;
        return `${c.type === 'localIp' ? 'Local IP' : 'Remote IP'} ${c.ip} уже используется в интерфейсе "${conflictName}"`;
      });
      notify.error(`Обнаружено пересечение IP адресов:\n${conflictMessages.join('\n')}`);
      return;
    }
    
    if (interfaceModalMode === 'add') {
      setConfig(prev => ({
        ...prev,
        tunnelInterfaces: [...prev.tunnelInterfaces, normalizedData],
      }));
      notify.success('Интерфейс добавлен');
    } else {
      setConfig(prev => ({
        ...prev,
        tunnelInterfaces: prev.tunnelInterfaces.map(i => i.id === normalizedData.id ? normalizedData : i),
      }));
      notify.success('Интерфейс обновлён');
    }
    setInterfaceModalOpen(false);
    setEditingInterface(null);
  };

  const handleDeleteInterface = (iface) => {
    setItemToDelete(iface);
    setDeleteType('interface');
    setDeleteModalOpen(true);
  };

  // === CRUD для IPSec Passwords ===
  const handleAddIpsecPassword = () => {
    setEditingIpsecPassword({ name: '', password: '', description: '' });
    setIpsecPasswordModalMode('add');
    setIpsecPasswordModalOpen(true);
  };

  const handleEditIpsecPassword = async (passwordId) => {
    try {
      const response = await api.get(`/ipsec-passwords/${passwordId}`);
      setEditingIpsecPassword(response.data);
      setIpsecPasswordModalMode('edit');
      setIpsecPasswordModalOpen(true);
    } catch (error) {
      console.error('Error fetching IPSec password:', error);
      notify.error('Не удалось загрузить пароль');
    }
  };

  const handleSaveIpsecPassword = async () => {
    if (!editingIpsecPassword.name || !editingIpsecPassword.password) {
      notify.error('Имя и пароль обязательны');
      return;
    }

    try {
      let savedPasswordId = null;
      if (ipsecPasswordModalMode === 'add') {
        const response = await api.post('/ipsec-passwords', {
          name: editingIpsecPassword.name,
          password: editingIpsecPassword.password,
          description: editingIpsecPassword.description || ''
        });
        notify.success('IPSec пароль создан');
        // Получаем ID созданного пароля из ответа
        savedPasswordId = response.data?.id || null;
      } else {
        await api.put(`/ipsec-passwords/${editingIpsecPassword.id}`, {
          name: editingIpsecPassword.name,
          password: editingIpsecPassword.password,
          description: editingIpsecPassword.description || ''
        });
        notify.success('IPSec пароль обновлён');
        savedPasswordId = editingIpsecPassword.id;
      }
      
      await fetchIpsecPasswords();
      
      // Закрываем модал создания/редактирования пароля
      setIpsecPasswordModalOpen(false);
      setEditingIpsecPassword(null);
      
      // Если модал списка паролей открыт, закрываем его
      if (ipsecPasswordsListModalOpen) {
        setIpsecPasswordsListModalOpen(false);
      }
      
      // Если создан новый пароль и открыт шаблон интерфейса, автоматически выбираем его
      if (savedPasswordId && interfaceTemplateModalOpen && (templateType === 'IPSec' || templateType === 'GRE')) {
        setTemplateIpsecPasswordId(savedPasswordId);
      }
      
      // Если создан новый пароль и открыт модал интерфейса с типом IPSec или GRE, автоматически выбираем его
      if (savedPasswordId && interfaceModalOpen && (editingInterface?.type === 'IPSec' || editingInterface?.type === 'GRE')) {
        setEditingInterface({ ...editingInterface, ipsecPasswordId: savedPasswordId });
      }
    } catch (error) {
      console.error('Error saving IPSec password:', error);
      notify.error('Не удалось сохранить пароль');
    }
  };

  const handleDeleteIpsecPassword = async (passwordId) => {
    try {
      await api.delete(`/ipsec-passwords/${passwordId}`);
      notify.success('IPSec пароль удалён');
      await fetchIpsecPasswords();
    } catch (error) {
      console.error('Error deleting IPSec password:', error);
      notify.error('Не удалось удалить пароль');
    }
  };

  // === CRUD для IP Pools ===
  const handleAddPool = () => {
    setEditingPool(getEmptyIpPool());
    setPoolModalMode('add');
    setPoolModalOpen(true);
  };

  const handleEditPool = (pool) => {
    setEditingPool({ ...pool });
    setPoolModalMode('edit');
    setPoolModalOpen(true);
  };

  const handleSavePool = (poolData) => {
    if (poolModalMode === 'add') {
      setConfig(prev => ({
        ...prev,
        ipPools: [...prev.ipPools, poolData],
      }));
      notify.success('IP пул добавлен');
    } else {
      setConfig(prev => ({
        ...prev,
        ipPools: prev.ipPools.map(p => p.id === poolData.id ? poolData : p),
      }));
      notify.success('IP пул обновлён');
    }
    setPoolModalOpen(false);
    setEditingPool(null);
  };

  const handleDeletePool = (pool) => {
    setItemToDelete(pool);
    setDeleteType('pool');
    setDeleteModalOpen(true);
  };

  // === Подтверждение удаления ===
  const executeDelete = () => {
    if (!itemToDelete) return;
    
    if (deleteType === 'gateway') {
      setConfig(prev => ({
        ...prev,
        gateways: prev.gateways.filter(g => g.id !== itemToDelete.id),
      }));
      notify.success('Gateway удалён');
    } else if (deleteType === 'interface') {
      setConfig(prev => ({
        ...prev,
        tunnelInterfaces: prev.tunnelInterfaces.filter(i => i.id !== itemToDelete.id),
      }));
      notify.success('Интерфейс удалён');
    } else if (deleteType === 'pool') {
      setConfig(prev => ({
        ...prev,
        ipPools: prev.ipPools.filter(p => p.id !== itemToDelete.id),
      }));
      notify.success('IP пул удалён');
    }
    
    setDeleteModalOpen(false);
    setItemToDelete(null);
    setDeleteType('');
  };

  // === Copy to clipboard ===
  const copyToClipboard = async (text) => {
    try {
      await navigator.clipboard.writeText(text);
      notify.success('Скопировано');
    } catch {
      notify.error('Не удалось скопировать');
    }
  };

  // === Генерация кода MikroTik для настройки IP адресов интерфейсов ===
  const generateMikrotikInterfaceAddresses = async () => {
    const interfacesWithBothServers = (config.tunnelInterfaces || []).filter(i => 
      i.serverId && i.serverId2 && i.localIp && i.remoteIp
    );
    
    if (interfacesWithBothServers.length === 0) {
      return [];
    }
    
    // Загружаем пароли для интерфейсов с IPSec
    const passwordIds = [...new Set(interfacesWithBothServers
      .filter(i => i.ipsecPasswordId && i.ipsecPasswordId.trim() !== '')
      .map(i => i.ipsecPasswordId.trim())
    )];
    
    const passwordMap = {};
    for (const passwordId of passwordIds) {
      try {
        const response = await api.get(`/ipsec-passwords/${passwordId}`);
        const password = response.data?.password || '';
        if (password) {
          passwordMap[passwordId] = password;
        } else {
          console.warn(`IPSec password ${passwordId} loaded but empty`);
        }
      } catch (error) {
        console.error(`Error loading IPSec password ${passwordId}:`, error);
        passwordMap[passwordId] = '';
      }
    }
    
    // Группируем по серверам
    const interfacesByServer = {};
    interfacesWithBothServers.forEach(iface => {
      const server1 = getServerInfo(iface.serverId);
      const server2 = getServerInfo(iface.serverId2);
      
      if (!server1 || !server2) return;
      
      const server1Name = server1.dns || server1.ip || iface.serverId;
      const server2Name = server2.dns || server2.ip || iface.serverId2;
      
      // Имя интерфейса для первого сервера
      const interfaceName1 = iface.name || `${iface.type}-tunnel`;
      // Имя интерфейса для второго сервера - ВСЕГДА используем name2 если указано, иначе name
      const interfaceName2 = iface.name2 || iface.name || `${iface.type}-tunnel`;
      
      // Для первого сервера - используем localIp как local, remoteIp как remote
      if (!interfacesByServer[server1Name]) {
        interfacesByServer[server1Name] = {
          serverInfo: server1,
          interfaces: []
        };
      }
      interfacesByServer[server1Name].interfaces.push({
        interfaceName: interfaceName1,
        localIp: iface.localIp,
        remoteIp: iface.remoteIp,
        type: iface.type,
        server2Name,
        server2Info: server2,
        ipsecPasswordId: (iface.ipsecPasswordId && iface.ipsecPasswordId.trim() !== '') ? iface.ipsecPasswordId.trim() : null,
        ipsecPassword: (iface.ipsecPasswordId && iface.ipsecPasswordId.trim() !== '') ? (passwordMap[iface.ipsecPasswordId.trim()] || null) : null,
        mtu: iface.mtu || null
      });
      
      // Для второго сервера - МЕНЯЕМ МЕСТАМИ: remoteIp становится localIp, localIp становится remoteIp
      // И ВСЕГДА используем name2 (или name если name2 не указано)
      if (!interfacesByServer[server2Name]) {
        interfacesByServer[server2Name] = {
          serverInfo: server2,
          interfaces: []
        };
      }
      interfacesByServer[server2Name].interfaces.push({
        interfaceName: interfaceName2, // Используем name2 для второго сервера
        localIp: iface.remoteIp, // На втором сервере remoteIp первого становится localIp
        remoteIp: iface.localIp, // На втором сервере localIp первого становится remoteIp
        type: iface.type,
        server2Name: server1Name,
        server2Info: server1,
        ipsecPasswordId: (iface.ipsecPasswordId && iface.ipsecPasswordId.trim() !== '') ? iface.ipsecPasswordId.trim() : null,
        ipsecPassword: (iface.ipsecPasswordId && iface.ipsecPasswordId.trim() !== '') ? (passwordMap[iface.ipsecPasswordId.trim()] || null) : null,
        mtu: iface.mtu || null
      });
    });

    // Сортируем серверы по имени для консистентности
    const sortedServers = Object.entries(interfacesByServer).sort(([a], [b]) => a.localeCompare(b));

    const blocks = [];
    sortedServers.forEach(([serverName, serverData]) => {
      const server = serverData.serverInfo;
      
      let code = `# Настройка IP адресов интерфейсов для сервера: ${serverName}\n`;
      if (server.provider) {
        code += `# Провайдер: ${server.provider}\n`;
      }
      if (server.country) {
        code += `# Страна: ${server.country}\n`;
      }
      if (server.ip && server.ip !== serverName) {
        code += `# IP: ${server.ip}\n`;
      }
      code += '\n';
      
      serverData.interfaces.forEach((iface, ifaceIndex) => {
        code += `# Интерфейс ${ifaceIndex + 1}: ${iface.interfaceName} (${iface.type})\n`;
        code += `# Связь с сервером: ${iface.server2Name}\n`;
        code += `# Local IP: ${iface.localIp}\n`;
        code += `# Remote IP: ${iface.remoteIp}\n`;
        
        // Для GRE туннелей - создаем туннель, опционально с IPSec через ipsec-secret
        if (iface.type === 'GRE') {
          // Используем DNS домен для remote-address, если он есть, иначе IP
          const remoteAddress = iface.server2Info?.dns || iface.server2Info?.ip || iface.server2Name;
          
          // Проверяем наличие пароля: ipsecPasswordId должен быть не пустым и пароль должен быть загружен
          const hasIpsecPassword = iface.ipsecPasswordId && 
                                   iface.ipsecPasswordId.trim() !== '' && 
                                   iface.ipsecPassword && 
                                   iface.ipsecPassword.trim() !== '';
          
          if (hasIpsecPassword) {
            // GRE туннель с IPSec через ipsec-secret (автоматическая настройка)
            code += `# Создание GRE туннеля с IPSec (автоматическая настройка через ipsec-secret)\n`;
            const mtuParam = iface.mtu ? ` mtu=${iface.mtu}` : '';
            code += `/interface gre add name="${iface.interfaceName}" remote-address=${remoteAddress} keepalive=10s allow-fast-path=no ipsec-secret="${iface.ipsecPassword}"${mtuParam}\n`;
            code += '\n';
          } else {
            // GRE туннель без IPSec (голый GRE)
            code += `# Создание GRE туннеля (без IPSec)\n`;
            const mtuParam = iface.mtu ? ` mtu=${iface.mtu}` : '';
            code += `/interface gre add name="${iface.interfaceName}" remote-address=${remoteAddress} keepalive=10s allow-fast-path=no${mtuParam}\n`;
            code += '\n';
          }
        }
        
        // Добавляем IP адрес на интерфейс
        code += `/ip address add address=${iface.localIp}/30 interface="${iface.interfaceName}" comment="Interface: ${iface.interfaceName} (${iface.type}) to ${iface.server2Name}"\n`;
        code += '\n';
      });
      
      code += '# Проверка настроенных адресов на этом сервере:\n';
      code += '# /ip address print\n';
      
      blocks.push({
        type: 'interface-addresses',
        serverName,
        server,
        code
      });
    });
    
    return blocks;
  };

  // === Генерация кода MikroTik для рекурсивных маршрутов ===
  const generateMikrotikRecursiveRoutes = async () => {
    const recursiveGateways = (config.gateways || []).filter(gw => gw.type === 'recursive');
    
    const blocks = [];

    // Если есть рекурсивные gateway, генерируем блоки для них
    if (recursiveGateways.length > 0) {
      // Группируем по серверам для удобства
      const gatewaysByServer = {};
      recursiveGateways.forEach(gw => {
        const serverId = gw.serverId || '__unassigned__';
        if (!gatewaysByServer[serverId]) {
          gatewaysByServer[serverId] = [];
        }
        gatewaysByServer[serverId].push(gw);
      });

      // Генерируем блоки для рекурсивных маршрутов по серверам
      Object.entries(gatewaysByServer).forEach(([serverId, gateways]) => {
      const server = getServerInfo(serverId);
      const serverName = server?.dns || server?.ip || serverId;
      
      let code = `# Рекурсивные маршруты для сервера: ${serverName}\n`;
      if (server?.provider) {
        code += `# Провайдер: ${server.provider}\n`;
      }
      if (server?.country) {
        code += `# Страна: ${server.country}\n`;
      }
      code += '\n';
      code += '# Удаление существующих рекурсивных маршрутов (опционально)\n';
      code += '/ip route remove [find comment~"Recursive"]\n\n';
      
      let validRoutesCount = 0;
      
      gateways.forEach(gw => {
        // Поддержка старого формата (parentGatewayId) и нового (parentGateways)
        const parentGatewaysList = gw.parentGateways && Array.isArray(gw.parentGateways) && gw.parentGateways.length > 0
          ? gw.parentGateways
          : (gw.parentGatewayId ? [{ id: gw.parentGatewayId, distance: undefined }] : []);
        
        if (parentGatewaysList.length === 0) {
          code += `# Gateway "${gw.ip || 'без IP'}" - родительские gateway/интерфейсы не указаны, пропущен\n`;
          return;
        }
        
        if (!gw.ip) {
          code += `# Gateway без IP адреса - пропущен\n`;
          return;
        }
        
        // Обрабатываем каждый родительский gateway
        parentGatewaysList.forEach((parentRef, parentIndex) => {
          const parent = getParentGateway(parentRef.id);
          
          if (!parent) {
            code += `# Gateway "${gw.ip}" - родительский gateway/интерфейс "${parentRef.id}" не найден, пропущен\n`;
            return;
          }
          
          // Определяем IP родителя в зависимости от типа
          const parentIp = parent.parentType === 'interface' ? parent.remoteIp : parent.ip;
          
          if (!parentIp) {
            const parentType = parent.parentType === 'interface' ? 'интерфейс' : 'gateway';
            code += `# Gateway "${gw.ip}" - родительский ${parentType} не имеет IP, пропущен\n`;
            return;
          }
          
          validRoutesCount++;
          
          // Создаём маршрут для рекурсивного gateway
          const parentLabel = parent.parentType === 'interface' 
            ? `интерфейс ${parent.name || parent.interfaceType || 'interface'} (${parent.remoteIp})`
            : `gateway ${parent.ip}`;
          
          const distanceSuffix = parentRef.distance !== undefined && parentRef.distance !== null ? ` (distance: ${parentRef.distance})` : '';
          code += `# Рекурсивный gateway: ${gw.ip}${distanceSuffix}\n`;
          code += `# Родительский: ${parentLabel}\n`;
          
          // Формируем gateway: для интерфейсов добавляем имя через %, для gateway - только IP
          const gatewayValue = parent.parentType === 'interface'
            ? `${parentIp}%${parent.name || parent.interfaceType || 'interface'}`
            : parentIp;
          
          // Создаём маршрут к IP рекурсивного gateway через родительский
          const comment = gw.description 
            ? `Recursive: ${gw.description} -> ${parentIp}${distanceSuffix}` 
            : `Recursive: ${gw.ip} -> ${parentIp}${distanceSuffix}`;
          
          // Формируем команду с distance, если указан
          const distanceParam = parentRef.distance !== undefined && parentRef.distance !== null ? ` distance=${parentRef.distance}` : '';
          code += `/ip route add dst-address=${gw.ip}/32 gateway=${gatewayValue}${distanceParam} comment="${comment}"\n`;
          
          // Если у рекурсивного gateway есть описание с указанием на default route
          if (gw.description && (gw.description.toLowerCase().includes('default') || gw.description.toLowerCase().includes('0.0.0.0'))) {
            code += `# Дополнительный default route через рекурсивный gateway${distanceSuffix}\n`;
            const defaultComment = gw.description ? `Recursive: ${gw.description} (default)${distanceSuffix}` : `Recursive: ${gw.ip} (default)${distanceSuffix}`;
            code += `/ip route add dst-address=0.0.0.0/0 gateway=${gatewayValue}${distanceParam} comment="${defaultComment}"\n`;
          }
          code += '\n';
        });
      });
      
      code += '# Проверка созданных маршрутов:\n';
      code += '# /ip route print where comment~"Recursive"\n';
      code += `# Всего создано маршрутов: ${validRoutesCount}\n`;
      
      if (validRoutesCount > 0) {
        blocks.push({
          type: 'recursive-routes',
          serverName,
          server,
          code
        });
      }
      });
    }
    
    // Генерируем блоки для IP адресов интерфейсов
    const interfaceBlocks = await generateMikrotikInterfaceAddresses();
    if (interfaceBlocks && interfaceBlocks.length > 0) {
      blocks.push(...interfaceBlocks);
    }
    
    return blocks;
  };

  // === Обработчик кнопки "Код для MikroTik" ===
  const handleGenerateMikrotikCode = async () => {
    setLoading(true);
    try {
      const code = await generateMikrotikRecursiveRoutes();
      setGeneratedMikrotikCode(code);
      setMikrotikCodeModalOpen(true);
    } catch (error) {
      console.error('Error generating MikroTik code:', error);
      notify.error('Ошибка при генерации кода MikroTik');
    } finally {
      setLoading(false);
    }
  };

  // === Копирование кода MikroTik ===
  const handleCopyMikrotikCode = async (codeToCopy) => {
    if (!codeToCopy) {
      notify.error('Нет кода для копирования');
      return;
    }
    
    try {
      if (navigator.clipboard && navigator.clipboard.writeText) {
        await navigator.clipboard.writeText(codeToCopy);
        notify.success('Код скопирован в буфер обмена!');
      } else {
        // Fallback для старых браузеров
        const textArea = document.createElement('textarea');
        textArea.value = codeToCopy;
        textArea.style.position = 'fixed';
        textArea.style.left = '-999999px';
        document.body.appendChild(textArea);
        textArea.focus();
        textArea.select();
        try {
          document.execCommand('copy');
          notify.success('Код скопирован в буфер обмена!');
        } catch (err) {
          notify.error('Не удалось скопировать код');
        }
        document.body.removeChild(textArea);
      }
    } catch (err) {
      console.error('Error copying to clipboard:', err);
      notify.error('Не удалось скопировать код');
    }
  };

  // === Копирование отдельного блока кода ===
  const handleCopyBlock = async (code) => {
    await handleCopyMikrotikCode(code);
  };

  // === Копирование всего кода ===
  const handleCopyAllMikrotikCode = async () => {
    const fullCode = Array.isArray(generatedMikrotikCode) && generatedMikrotikCode.length > 0
      ? generatedMikrotikCode.map(block => block.code).join('\n\n')
      : '';
    await handleCopyMikrotikCode(fullCode);
  };

  // === Группировка блоков по серверам ===
  const groupedMikrotikCode = useMemo(() => {
    if (!Array.isArray(generatedMikrotikCode) || generatedMikrotikCode.length === 0) {
      return {};
    }
    
    const grouped = {};
    generatedMikrotikCode.forEach(block => {
      const serverName = block.serverName || '__unassigned__';
      if (!grouped[serverName]) {
        grouped[serverName] = {
          server: block.server,
          serverName: serverName,
          blocks: []
        };
      }
      grouped[serverName].blocks.push(block);
    });
    
    return grouped;
  }, [generatedMikrotikCode]);

  // === Получение названия типа блока ===
  const getBlockTypeLabel = (type) => {
    switch (type) {
      case 'recursive-routes':
        return 'Рекурсивные маршруты';
      case 'interface-addresses':
        return 'IP адреса интерфейсов';
      default:
        return 'Конфигурация';
    }
  };

  // === Получение цвета провайдера ===
  const getProviderColor = (provider) => {
    if (!provider) return 'secondary';
    // Ищем точное совпадение
    const exact = GATEWAY_PROVIDERS.find(gp => 
      gp.value === provider || 
      gp.label.toLowerCase() === provider.toLowerCase()
    );
    if (exact) return exact.color;
    // Проверяем частичное совпадение
    const partial = GATEWAY_PROVIDERS.find(gp => 
      provider.toLowerCase().includes(gp.value.toLowerCase()) ||
      provider.toLowerCase().includes(gp.label.toLowerCase())
    );
    return partial?.color || 'secondary';
  };

  const getInterfaceTypeColor = (type) => {
    const t = INTERFACE_TYPES.find(it => it.value === type);
    return t?.color || 'secondary';
  };

  // === Рендер карточки сервера с его элементами ===
  const renderServerGroup = (serverId, items, type) => {
    const server = getServerInfo(serverId);
    const isUnassigned = serverId === '__unassigned__';
    
    return (
      <div key={serverId} className="mb-4">
        {/* Server header */}
        <div className="d-flex align-items-center mb-2 px-1">
          <div className="d-flex align-items-center">
            {isUnassigned ? (
              <>
                <span className="avatar avatar-sm bg-secondary-lt me-2">
                  <IconServer size={16} className="text-muted" />
                </span>
                <span className="text-muted">Без привязки к серверу</span>
              </>
            ) : (
              <>
                <span className="avatar avatar-sm bg-primary-lt me-2">
                  <IconServer size={16} className="text-primary" />
                </span>
                <div>
                  <span className="fw-medium">
                    {server?.dns ? server.dns.split('.')[0] : (server?.name || serverId)}
                  </span>
                  {server?.dns && (
                    <span className="text-muted ms-2 small">
                      {server.dns}
                    </span>
                  )}
                  {server && (
                    <span className="text-muted ms-2 small">
                      {server.ip}
                      {server.country && (
                        <span className="ms-1">{countryToFlag(server.country)} {server.country}</span>
                      )}
                    </span>
                  )}
                </div>
              </>
            )}
          </div>
          <span className="badge bg-secondary-lt ms-auto">{items.length}</span>
        </div>
        
        {/* Items */}
        <div className="row row-cards">
          {items.map(item => (
            <div key={item.id} className="col-12 col-md-6 col-lg-6">
              {type === 'gateway' ? renderGatewayCard(item) : 
               type === 'interface' ? renderInterfaceCard(item, serverId) :
               type === 'pool' ? renderPoolCard(item) : null}
            </div>
          ))}
        </div>
      </div>
    );
  };

  // === Получение родительского gateway или интерфейса ===
  const getParentGateway = (parentId) => {
    if (!parentId) return null;
    
    // Сначала ищем в gateway
    const gateway = config.gateways?.find(g => g.id === parentId);
    if (gateway) {
      return { 
        parentType: 'gateway', // Используем parentType чтобы не конфликтовать с type интерфейса
        ...gateway,
        ip: gateway.ip // Явно указываем IP для gateway
      };
    }
    
    // Если не найден, ищем в интерфейсах
    const iface = config.tunnelInterfaces?.find(i => i.id === parentId);
    if (iface) {
      return { 
        parentType: 'interface', // Используем parentType чтобы не конфликтовать с type интерфейса
        ...iface,
        remoteIp: iface.remoteIp, // Явно указываем remoteIp для интерфейса
        localIp: iface.localIp,
        name: iface.name,
        interfaceType: iface.type // Сохраняем тип интерфейса (GRE, WireGuard и т.д.) отдельно
      };
    }
    
    // Если не найден ни gateway, ни интерфейс - логируем для отладки
    console.warn('Parent gateway/interface not found:', parentId, {
      availableGateways: config.gateways?.map(g => g.id),
      availableInterfaces: config.tunnelInterfaces?.map(i => i.id)
    });
    
    return null;
  };

  // === Рендер карточки IP Pool ===
  const renderPoolCard = (pool) => {
    const server = getServerInfo(pool.serverId);
    const serverCountry = server?.country || '';
    
    // Определяем цвет индикатора (зеленый для IP пулов)
    const indicatorColor = 'green';
    const IndicatorIcon = IconDatabase;
    
    return (
      <div className="card mb-2" style={{ borderRadius: '12px', maxWidth: '100%' }}>
        <div className="card-body p-0">
          <div className="d-flex align-items-stretch">
            {/* Левая часть: тип индикатора */}
            <div 
              className={`d-flex align-items-center justify-content-center px-3 bg-${indicatorColor}-lt`}
              style={{ 
                minWidth: '100px',
                width: '100px',
                borderTopLeftRadius: '11px',
                borderBottomLeftRadius: '11px'
              }}
            >
              <div className="text-center">
                <div className="mb-1">
                  <IndicatorIcon size={20} className={`text-${indicatorColor}`} />
                </div>
                <div className={`fw-bold text-${indicatorColor}`} style={{ fontSize: '0.65rem', letterSpacing: '0.5px' }}>
                  Pool
                </div>
              </div>
            </div>
            
            {/* Центральная часть: информация */}
            <div className="flex-grow-1 py-2 px-3" style={{ minWidth: 0, flex: '1 1 auto', overflow: 'hidden' }}>
              {/* Верхняя строка: флаг, название */}
              <div className="d-flex align-items-center mb-1">
                <div className="d-flex align-items-center" style={{ flex: '0 0 auto', minWidth: 0 }}>
                  {serverCountry && (
                    <span className="me-2" style={{ fontSize: '1.25rem', flexShrink: 0 }}>{countryToFlag(serverCountry)}</span>
                  )}
                  <div>
                    <span className="fw-semibold">{pool.name || '—'}</span>
                  </div>
                </div>
              </div>
              
              {/* CIDR под названием */}
              {pool.cidr && (
                <div className="mb-1">
                  <code className="text-muted" style={{ fontSize: '0.875rem' }}>
                    {pool.cidr}
                  </code>
                </div>
              )}
              
              {/* Нижняя строка: DNS сервера */}
              <div className="d-flex align-items-center gap-2 flex-wrap">
                {server && (
                  <code className="text-muted" style={{ fontSize: '0.8rem', wordBreak: 'break-all', overflowWrap: 'break-word' }}>
                    {server.dns || server.ip || pool.serverId}
                  </code>
                )}
                {!server && pool.serverId && (
                  <code className="text-muted" style={{ fontSize: '0.8rem' }}>
                    {pool.serverId}
                  </code>
                )}
              </div>
            </div>
            
            {/* Правая часть: действия */}
            <div className="d-flex align-items-center gap-2 px-3 border-start" style={{ flexShrink: 0 }}>
              <button
                className="btn btn-outline-secondary btn-sm"
                onClick={() => handleEditPool(pool)}
              >
                <IconEdit size={16} className="me-1" />
                Изменить
              </button>
              <button
                className="btn btn-outline-danger btn-sm"
                onClick={() => handleDeletePool(pool)}
              >
                <IconTrash size={16} className="me-1" />
                Удалить
              </button>
            </div>
          </div>
        </div>
      </div>
    );
  };

  // === Рендер карточки Gateway ===
  const renderGatewayCard = (gateway) => {
    const server = getServerInfo(gateway.serverId);
    const provider = server?.provider || '';
    const serverCountry = server?.country || '';
    const gatewayCountry = gateway.country || '';
    const displayCountry = gatewayCountry || serverCountry;
    const gatewayType = GATEWAY_TYPES.find(t => t.value === gateway.type) || GATEWAY_TYPES[0];
    
    // Поддержка старого формата (parentGatewayId) и нового (parentGateways)
    const parentGatewaysList = gateway.type === 'recursive' 
      ? (gateway.parentGateways && Array.isArray(gateway.parentGateways) && gateway.parentGateways.length > 0
          ? gateway.parentGateways
          : (gateway.parentGatewayId ? [{ id: gateway.parentGatewayId, distance: undefined }] : []))
      : [];
    
    // Получаем информацию о первом родительском gateway для отображения
    const firstParent = parentGatewaysList.length > 0 ? getParentGateway(parentGatewaysList[0].id) : null;
    
    // Определяем тип индикатора (как в ServerCard)
    const indicatorType = gateway.type === 'recursive' ? 'Рекурсивный' : 'Прямой';
    const indicatorColor = gateway.type === 'recursive' ? 'red' : 'blue';
    const IndicatorIcon = gateway.type === 'recursive' ? IconArrowsRightLeft : IconRouter;
    
    // Формируем текст для зеленого блока
    let displayText = '';
    if (gateway.type === 'direct') {
      // Для прямого gateway: 0.0.0.0/0 -> IP адрес
      displayText = gateway.ip ? `0.0.0.0/0 → ${gateway.ip}` : '';
    } else if (gateway.type === 'recursive' && firstParent) {
      // Для рекурсивного: IP адрес -> IP адрес первого родительского gateway
      const parentIp = firstParent.parentType === 'interface' 
        ? firstParent.remoteIp 
        : firstParent.ip;
      displayText = gateway.ip && parentIp ? `${gateway.ip} → ${parentIp}` : '';
      // Если несколько родительских gateway, добавляем информацию
      if (parentGatewaysList.length > 1) {
        displayText += ` (+${parentGatewaysList.length - 1})`;
      }
    }
    
    return (
      <div className="card mb-2" style={{ borderRadius: '12px', maxWidth: '100%' }}>
        <div className="card-body p-0">
          <div className="d-flex align-items-stretch">
            {/* Левая часть: тип индикатора (как в ServerCard) */}
            <div 
              className={`d-flex align-items-center justify-content-center px-3 bg-${indicatorColor}-lt`}
              style={{ 
                minWidth: '100px',
                width: '100px',
                borderTopLeftRadius: '11px',
                borderBottomLeftRadius: '11px'
              }}
            >
              <div className="text-center">
                <div className="mb-1">
                  <IndicatorIcon size={20} className={`text-${indicatorColor}`} />
                </div>
                <div className={`fw-bold text-${indicatorColor}`} style={{ fontSize: '0.65rem', letterSpacing: '0.5px' }}>
                  {indicatorType}
                </div>
              </div>
            </div>
            
            {/* Центральная часть: информация */}
            <div className="flex-grow-1 py-2 px-3" style={{ minWidth: 0, flex: '1 1 auto', overflow: 'hidden' }}>
              {/* Верхняя строка: флаг, название */}
              <div className="d-flex align-items-center mb-1">
                <div className="d-flex align-items-center" style={{ flex: '0 0 auto', minWidth: 0 }}>
                  {displayCountry && (
                    <span className="me-2" style={{ fontSize: '1.25rem', flexShrink: 0 }}>{countryToFlag(displayCountry)}</span>
                  )}
                  <div>
                    <span className="fw-semibold">{gateway.description || gateway.ip || '—'}</span>
                  </div>
                </div>
              </div>
              
              {/* Маршрут ip->ip сразу под названием */}
              {displayText && (
                <div className="mb-1">
                  <span className="badge bg-success-lt text-success" style={{ whiteSpace: 'nowrap', fontSize: '0.875rem' }}>
                    {displayText}
                  </span>
                </div>
              )}
              
              {/* Нижняя строка: DNS */}
              <div className="d-flex align-items-center gap-2 flex-wrap">
                {server && (
                  <code className="text-muted" style={{ fontSize: '0.8rem', wordBreak: 'break-all', overflowWrap: 'break-word' }}>
                    {server.dns || server.ip || gateway.serverId}
                  </code>
                )}
              </div>
            </div>
            
            {/* Правая часть: действия */}
            <div className="d-flex align-items-center gap-2 px-3 border-start" style={{ flexShrink: 0 }}>
              <button
                className="btn btn-outline-secondary btn-sm"
                onClick={() => handleEditGateway(gateway)}
              >
                <IconEdit size={16} className="me-1" />
                Изменить
              </button>
              <button
                className="btn btn-outline-danger btn-sm"
                onClick={() => handleDeleteGateway(gateway)}
              >
                <IconTrash size={16} className="me-1" />
                Удалить
              </button>
            </div>
          </div>
        </div>
      </div>
    );
  };

  // === Рендер карточки Interface ===
  const renderInterfaceCard = (iface, currentServerId) => {
    const server = getServerInfo(iface.serverId);
    const server2 = getServerInfo(iface.serverId2);
    
    // Определяем, для какого сервера отображается карточка
    const isForServer2 = currentServerId && iface.serverId2 && (() => {
      const currentServer = getServerInfo(currentServerId);
      const targetServer2 = getServerInfo(iface.serverId2);
      if (!currentServer || !targetServer2) return false;
      return (
        currentServer.id === targetServer2.id ||
        currentServer.ip === targetServer2.ip ||
        currentServer.dns === targetServer2.dns ||
        currentServerId === iface.serverId2 ||
        currentServerId === targetServer2.id ||
        currentServerId === targetServer2.ip ||
        currentServerId === targetServer2.dns
      );
    })();
    
    // Имя интерфейса зависит от того, для какого сервера отображается
    const interfaceName = isForServer2 
      ? (iface.name2 || iface.name || '—')
      : (iface.name || '—');
    
    // IP адреса также зависят от того, для какого сервера отображается
    const displayLocalIp = isForServer2 ? (iface.remoteIp || '—') : (iface.localIp || '—');
    const displayRemoteIp = isForServer2 ? (iface.localIp || '—') : (iface.remoteIp || '—');
    
    // Определяем сервер для отображения
    const displayServer = isForServer2 ? server2 : server;
    const displayServerName = displayServer?.dns || displayServer?.ip || (isForServer2 ? iface.serverId2 : iface.serverId);
    const displayCountry = displayServer?.country || '';
    const interfaceTypeColor = getInterfaceTypeColor(iface.type);
    
    // Определяем отображаемый IP для зеленого блока (remote IP другого сервера)
    const displayIp = displayRemoteIp !== '—' ? displayRemoteIp : displayLocalIp;
    
    return (
      <div className="card mb-2" style={{ borderRadius: '12px', maxWidth: '100%' }}>
        <div className="card-body p-0">
          <div className="d-flex align-items-stretch">
            {/* Левая часть: тип интерфейса (как в ServerCard) */}
            <div 
              className={`d-flex align-items-center justify-content-center px-3 bg-${interfaceTypeColor}-lt`}
              style={{ 
                minWidth: '100px',
                width: '100px',
                borderTopLeftRadius: '11px',
                borderBottomLeftRadius: '11px'
              }}
            >
              <div className="text-center">
                <div className="mb-1">
                  <IconRouter size={20} className={`text-${interfaceTypeColor}`} />
                </div>
                <div className={`fw-bold text-${interfaceTypeColor}`} style={{ fontSize: '0.65rem', letterSpacing: '0.5px' }}>
                  {iface.type}
                </div>
              </div>
            </div>
            
            {/* Центральная часть: информация */}
            <div className="flex-grow-1 py-2 px-3" style={{ minWidth: 0, flex: '1 1 auto', overflow: 'hidden' }}>
              {/* Верхняя строка: флаг, название */}
              <div className="d-flex align-items-center mb-1">
                <div className="d-flex align-items-center" style={{ flex: '0 0 auto', minWidth: 0 }}>
                  {displayCountry && (
                    <span className="me-2" style={{ fontSize: '1.25rem', flexShrink: 0 }}>{countryToFlag(displayCountry)}</span>
                  )}
                  <div>
                    <span className="fw-semibold">{interfaceName}</span>
                  </div>
                </div>
              </div>
              
              {/* Маршрут между Local IP и Remote IP сразу под названием */}
              {displayLocalIp !== '—' && displayRemoteIp !== '—' && (
                <div className="mb-1">
                  <span className="badge bg-success-lt text-success" style={{ whiteSpace: 'nowrap', fontSize: '0.875rem' }}>
                    {displayLocalIp} → {displayRemoteIp}
                  </span>
                </div>
              )}
              
              {/* Нижняя строка: DNS */}
              <div className="d-flex align-items-center gap-2 flex-wrap">
                {displayServerName && (
                  <code className="text-muted" style={{ fontSize: '0.8rem', wordBreak: 'break-all', overflowWrap: 'break-word' }}>
                    {displayServerName}
                  </code>
                )}
              </div>
            </div>
            
            {/* Правая часть: действия */}
            <div className="d-flex align-items-center gap-2 px-3 border-start" style={{ flexShrink: 0 }}>
              <button
                className="btn btn-outline-secondary btn-sm"
                onClick={() => handleEditInterface(iface)}
              >
                <IconEdit size={16} className="me-1" />
                Изменить
              </button>
              <button
                className="btn btn-outline-danger btn-sm"
                onClick={() => handleDeleteInterface(iface)}
              >
                <IconTrash size={16} className="me-1" />
                Удалить
              </button>
            </div>
          </div>
        </div>
      </div>
    );
  };

  return (
    <div className="network-config-manager">
      {/* Page Header */}
      <div className="page-header d-print-none mb-4">
        <div className="row align-items-center">
          <div className="col">
            <div className="page-pretitle">Управление</div>
            <h2 className="page-title d-flex align-items-center">
              <IconNetwork className="me-2" size={28} />
              Сетевые настройки
            </h2>
          </div>
          <div className="col-auto ms-auto d-print-none">
            <div className="btn-list">
              {/* Tabs as button group */}
              <div className="btn-group me-2" role="group">
                <button
                  className={`btn ${activeTab === 'gateways' ? 'btn-primary' : 'btn-outline-primary'}`}
                  onClick={() => setActiveTab('gateways')}
                >
                  <IconWorld size={16} className="me-1 d-none d-sm-inline" />
                  Gateways
                  <span className={`badge ms-1 ${activeTab === 'gateways' ? 'bg-white text-primary' : 'bg-primary-lt text-primary'}`}>
                    {config.gateways?.length || 0}
                  </span>
                </button>
                <button
                  className={`btn ${activeTab === 'interfaces' ? 'btn-primary' : 'btn-outline-primary'}`}
                  onClick={() => setActiveTab('interfaces')}
                >
                  <IconRouter size={16} className="me-1 d-none d-sm-inline" />
                  Интерфейсы
                  <span className={`badge ms-1 ${activeTab === 'interfaces' ? 'bg-white text-primary' : 'bg-primary-lt text-primary'}`}>
                    {config.tunnelInterfaces?.length || 0}
                  </span>
                </button>
                <button
                  className={`btn ${activeTab === 'pools' ? 'btn-primary' : 'btn-outline-primary'}`}
                  onClick={() => setActiveTab('pools')}
                >
                  <IconDatabase size={16} className="me-1 d-none d-sm-inline" />
                  IP пулы
                  <span className={`badge ms-1 ${activeTab === 'pools' ? 'bg-white text-primary' : 'bg-primary-lt text-primary'}`}>
                    {config.ipPools?.length || 0}
                  </span>
                </button>
                <button
                  className={`btn ${activeTab === 'ip-registry' ? 'btn-primary' : 'btn-outline-primary'}`}
                  onClick={() => setActiveTab('ip-registry')}
                >
                  <IconList size={16} className="me-1 d-none d-sm-inline" />
                  Реестр IP
                  <span className={`badge ms-1 ${activeTab === 'ip-registry' ? 'bg-white text-primary' : 'bg-primary-lt text-primary'}`}>
                    {ipRegistry.length}
                  </span>
                  {ipRegistry.some(item => item.hasConflict) && (
                    <span className="badge bg-danger ms-1" title="Обнаружены конфликты IP адресов">
                      !
                    </span>
                  )}
                </button>
              </div>

              <button
                type="button"
                className="btn btn-outline-secondary"
                onClick={() => { fetchConfig(); fetchServers(); }}
                disabled={loading}
              >
                <IconRefresh size={16} className={loading ? 'spin' : ''} />
              </button>
              <button
                type="button"
                className="btn btn-outline-primary"
                onClick={handleGenerateMikrotikCode}
                disabled={loading || (
                  (config.gateways || []).filter(gw => gw.type === 'recursive').length === 0 &&
                  (config.tunnelInterfaces || []).filter(i => i.serverId && i.serverId2 && i.localIp && i.remoteIp).length === 0
                )}
                title="Генерировать код MikroTik для рекурсивных маршрутов и IP адресов интерфейсов"
              >
                <IconCode size={16} className="me-1" />
                Код для MikroTik
              </button>
              <button
                type="button"
                className="btn btn-primary"
                onClick={handleSave}
                disabled={saving}
              >
                <IconDatabase size={16} className={`me-1 ${saving ? 'spin' : ''}`} />
                Сохранить
              </button>
            </div>
          </div>
        </div>
      </div>

      {/* Toolbar */}
      <div className="card mb-3">
        <div className="card-body py-2">
          <div className="row g-2 align-items-center">
            {/* Search */}
            <div className="col-12 col-md-4 col-lg-3">
              <div className="input-icon">
                <span className="input-icon-addon">
                  <IconSearch size={16} />
                </span>
                <input
                  type="text"
                  className="form-control"
                  placeholder="Поиск..."
                  value={searchTerm}
                  onChange={(e) => setSearchTerm(e.target.value)}
                />
                {searchTerm && (
                  <span className="input-icon-addon" style={{ pointerEvents: 'auto', cursor: 'pointer' }} onClick={() => setSearchTerm('')}>
                    <IconX size={16} />
                  </span>
                )}
              </div>
            </div>
            
            {/* Server filter */}
            {(activeTab === 'gateways' || activeTab === 'interfaces' || activeTab === 'pools') && uniqueServersInConfig.length > 0 && (
              <div className="col-6 col-md-3 col-lg-2">
                <select
                  className="form-select"
                  value={serverFilter}
                  onChange={(e) => setServerFilter(e.target.value)}
                >
                  <option value="">Все серверы</option>
                  {uniqueServersInConfig.map(s => (
                    <option key={s.id} value={s.id}>
                      {s.label}
                    </option>
                  ))}
                </select>
              </div>
            )}
            
            {/* Provider filter for gateways - берем уникальные провайдеры из серверов */}
            {activeTab === 'gateways' && (
              <div className="col-6 col-md-3 col-lg-2">
                <select
                  className="form-select"
                  value={providerFilter}
                  onChange={(e) => setProviderFilter(e.target.value)}
                >
                  <option value="">Все провайдеры</option>
                  {Array.from(new Set(servers.map(s => s.provider).filter(Boolean))).map(provider => (
                    <option key={provider} value={provider}>{provider}</option>
                  ))}
                </select>
              </div>
            )}
            
            {/* Type filter for interfaces */}
            {activeTab === 'interfaces' && (
              <div className="col-6 col-md-3 col-lg-2">
                <select
                  className="form-select"
                  value={typeFilter}
                  onChange={(e) => setTypeFilter(e.target.value)}
                >
                  <option value="">Все типы</option>
                  {INTERFACE_TYPES.map(t => (
                    <option key={t.value} value={t.value}>{t.label}</option>
                  ))}
                </select>
              </div>
            )}
            
            {/* Reset filters */}
            {hasActiveFilters && (
              <div className="col-auto">
                <button className="btn btn-ghost-secondary btn-sm" onClick={resetFilters}>
                  <IconX size={14} className="me-1" />
                  Сбросить
                </button>
              </div>
            )}
            
            <div className="col-auto ms-auto d-flex gap-2">
              {/* View mode toggle */}
              {(activeTab === 'gateways' || activeTab === 'interfaces') && (
                <div className="btn-group btn-group-sm" role="group">
                  <button
                    className={`btn ${viewMode === 'cards' ? 'btn-secondary' : 'btn-outline-secondary'}`}
                    onClick={() => setViewMode('cards')}
                    title="Карточки"
                  >
                    <IconLayoutGrid size={16} />
                  </button>
                  <button
                    className={`btn ${viewMode === 'table' ? 'btn-secondary' : 'btn-outline-secondary'}`}
                    onClick={() => setViewMode('table')}
                    title="Таблица"
                  >
                    <IconList size={16} />
                  </button>
                </div>
              )}
              
              {/* Add button */}
              {activeTab === 'gateways' && (
                <button className="btn btn-primary btn-sm" onClick={handleAddGateway}>
                  <IconPlus size={16} className="me-1" />
                  Gateway
                </button>
              )}
              {activeTab === 'interfaces' && (
                <>
                  <button className="btn btn-primary btn-sm" onClick={handleAddInterface}>
                    <IconPlus size={16} className="me-1" />
                    Интерфейс
                  </button>
                  <button 
                    className="btn btn-outline-primary btn-sm" 
                    onClick={() => setInterfaceTemplateModalOpen(true)}
                    title="Создать интерфейс из шаблона"
                  >
                    <IconSparkles size={16} className="me-1" />
                    Шаблон
                  </button>
                  <button 
                    className="btn btn-outline-secondary btn-sm" 
                    onClick={() => setIpsecPasswordsListModalOpen(true)}
                    title="Управление IPSec паролями"
                  >
                    <IconLock size={16} className="me-1" />
                    IPSec пароли
                  </button>
                </>
              )}
              {activeTab === 'pools' && (
                <button className="btn btn-primary btn-sm" onClick={handleAddPool}>
                  <IconPlus size={16} className="me-1" />
                  IP пул
                </button>
              )}
            </div>
          </div>
        </div>
      </div>

      {/* Content */}
      {loading ? (
        <div className="card">
          <div className="card-body text-center py-5">
            <div className="spinner-border text-primary" role="status"></div>
            <div className="text-muted mt-2">Загрузка...</div>
          </div>
        </div>
      ) : (
        <>
          {/* Gateways Tab */}
          {activeTab === 'gateways' && (
            <>
              {filteredGateways.length === 0 ? (
                <div className="card">
                  <div className="card-body text-center py-5">
                    <div className="mb-3">
                      <span className="avatar avatar-xl bg-primary-lt">
                        <IconWorld size={40} className="text-primary" />
                      </span>
                    </div>
                    <h3>Gateways не найдены</h3>
                    <p className="text-muted">
                      {hasActiveFilters 
                        ? 'Попробуйте изменить параметры фильтрации'
                        : 'Добавьте gateway для использования в конфигурациях серверов'
                      }
                    </p>
                    {!hasActiveFilters && (
                      <button className="btn btn-primary" onClick={handleAddGateway}>
                        <IconPlus size={16} className="me-1" />
                        Добавить Gateway
                      </button>
                    )}
                  </div>
                </div>
              ) : viewMode === 'cards' ? (
                // Grouped cards view
                <div>
                  {Object.entries(gatewaysByServer).map(([serverId, gateways]) =>
                    renderServerGroup(serverId, gateways, 'gateway')
                  )}
                </div>
              ) : (
                // Table view
                <div className="card">
                  <div className="table-responsive">
                    <table className="table card-table table-vcenter">
                      <thead>
                        <tr>
                          <th>IP адрес</th>
                          <th>Тип</th>
                          <th>Провайдер</th>
                          <th>Сервер</th>
                          <th>Страна</th>
                          <th className="text-end" style={{ width: 100 }}>Действия</th>
                        </tr>
                      </thead>
                      <tbody>
                        {filteredGateways.map(gateway => {
                          const server = getServerInfo(gateway.serverId);
                          const provider = server?.provider || '';
                          const serverCountry = server?.country || '';
                          const gatewayCountry = gateway.country || '';
                          const displayCountry = gatewayCountry || serverCountry;
                          const gatewayType = GATEWAY_TYPES.find(t => t.value === gateway.type) || GATEWAY_TYPES[0];
                          // Поддержка старого формата (parentGatewayId) и нового (parentGateways)
                          const parentGatewaysList = gateway.type === 'recursive' 
                            ? (gateway.parentGateways && Array.isArray(gateway.parentGateways) && gateway.parentGateways.length > 0
                                ? gateway.parentGateways
                                : (gateway.parentGatewayId ? [{ id: gateway.parentGatewayId, distance: undefined }] : []))
                            : [];
                          const firstParent = parentGatewaysList.length > 0 ? getParentGateway(parentGatewaysList[0].id) : null;
                          
                          return (
                            <tr key={gateway.id}>
                              <td>
                                <div className="d-flex align-items-center">
                                  <span className={`avatar avatar-xs bg-${gatewayType.color}-lt me-2`}>
                                    <IconCircleFilled size={8} className={`text-${gatewayType.color}`} />
                                  </span>
                                  <div className="flex-fill">
                                    <div className="d-flex align-items-center gap-1">
                                      <code className="fw-medium">{gateway.ip || '—'}</code>
                                      {gateway.ip && (
                                        <button
                                          className="btn btn-ghost-secondary btn-icon p-0"
                                          onClick={() => copyToClipboard(gateway.ip)}
                                          style={{ width: 20, height: 20 }}
                                          title="Копировать IP"
                                        >
                                          <IconCopy size={12} />
                                        </button>
                                      )}
                                    </div>
                                    {gateway.description && (
                                      <div className="text-muted small">{gateway.description}</div>
                                    )}
                                  </div>
                                </div>
                              </td>
                              <td>
                                <span className={`badge bg-${gatewayType.color}-lt text-${gatewayType.color}`}>
                                  {gatewayType.label}
                                </span>
                                {firstParent && (
                                  <div className="text-muted small mt-1">
                                    → {firstParent.parentType === 'interface' 
                                      ? `Интерфейс ${firstParent.name || firstParent.interfaceType || 'interface'} (${firstParent.remoteIp || '—'})`
                                      : firstParent.ip 
                                        ? `Gateway ${firstParent.ip}`
                                        : 'Gateway (не указан IP)'
                                    }
                                    {parentGatewaysList.length > 1 && (
                                      <span className="ms-1">(+{parentGatewaysList.length - 1})</span>
                                    )}
                                  </div>
                                )}
                              </td>
                              <td>
                                {provider ? (
                                  <span className={`badge bg-${getProviderColor(provider)}-lt text-${getProviderColor(provider)}`}>
                                    {provider}
                                  </span>
                                ) : '—'}
                              </td>
                              <td>
                                {server ? (
                                  <div className="d-flex align-items-center">
                                    <IconServer size={14} className="text-muted me-1" />
                                    <span>{server.dns || server.ip}</span>
                                  </div>
                                ) : gateway.serverId ? (
                                  <span className="text-muted">{gateway.serverId}</span>
                                ) : (
                                  <span className="text-muted">—</span>
                                )}
                              </td>
                              <td>
                                {displayCountry ? (
                                  <div>
                                    <span>{countryToFlag(displayCountry)} {displayCountry}</span>
                                    {gatewayCountry && serverCountry && gatewayCountry !== serverCountry && (
                                      <div className="text-muted small" style={{ fontSize: '0.7rem' }}>
                                        сервер: {serverCountry}
                                      </div>
                                    )}
                                  </div>
                                ) : '—'}
                              </td>
                              <td className="text-end">
                                <div className="btn-list gap-1 mb-0 justify-content-end">
                                  <button
                                    className="btn btn-ghost-primary btn-icon btn-sm"
                                    onClick={() => handleEditGateway(gateway)}
                                    title="Редактировать"
                                  >
                                    <IconEdit size={16} />
                                  </button>
                                  <button
                                    className="btn btn-ghost-danger btn-icon btn-sm"
                                    onClick={() => handleDeleteGateway(gateway)}
                                    title="Удалить"
                                  >
                                    <IconTrash size={16} />
                                  </button>
                                </div>
                              </td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>
                  </div>
                </div>
              )}
            </>
          )}

          {/* Interfaces Tab */}
          {activeTab === 'interfaces' && (
            <>
              {filteredInterfaces.length === 0 ? (
                <div className="card">
                  <div className="card-body text-center py-5">
                    <div className="mb-3">
                      <span className="avatar avatar-xl bg-blue-lt">
                        <IconRouter size={40} className="text-blue" />
                      </span>
                    </div>
                    <h3>Интерфейсы не найдены</h3>
                    <p className="text-muted">
                      {hasActiveFilters 
                        ? 'Попробуйте изменить параметры фильтрации'
                        : 'Добавьте туннельные интерфейсы для серверов'
                      }
                    </p>
                    {!hasActiveFilters && (
                      <button className="btn btn-primary" onClick={handleAddInterface}>
                        <IconPlus size={16} className="me-1" />
                        Добавить интерфейс
                      </button>
                    )}
                  </div>
                </div>
              ) : viewMode === 'cards' ? (
                // Grouped cards view
                <div>
                  {Object.entries(interfacesByServer).map(([serverId, interfaces]) =>
                    renderServerGroup(serverId, interfaces, 'interface')
                  )}
                </div>
              ) : (
                // Table view
                <div className="card">
                  <div className="table-responsive">
                    <table className="table card-table table-vcenter">
                      <thead>
                        <tr>
                          <th>Имя</th>
                          <th>Тип</th>
                          <th>Local IP</th>
                          <th>Remote IP</th>
                          <th>Серверы</th>
                          <th className="text-end" style={{ width: 100 }}>Действия</th>
                        </tr>
                      </thead>
                      <tbody>
                        {filteredInterfaces.map(iface => {
                          const server = getServerInfo(iface.serverId);
                          const server2 = getServerInfo(iface.serverId2);
                          return (
                            <tr key={iface.id}>
                              <td><strong>{iface.name || '—'}</strong></td>
                              <td>
                                <span className={`badge bg-${getInterfaceTypeColor(iface.type)}-lt text-${getInterfaceTypeColor(iface.type)}`}>
                                  {iface.type}
                                </span>
                              </td>
                              <td>
                                <code className="d-flex align-items-center gap-1">
                                  {iface.localIp || '—'}
                                  {iface.localIp && (
                                    <button
                                      className="btn btn-ghost-secondary btn-icon p-0"
                                      onClick={() => copyToClipboard(iface.localIp)}
                                      style={{ width: 20, height: 20 }}
                                    >
                                      <IconCopy size={12} />
                                    </button>
                                  )}
                                </code>
                              </td>
                              <td>
                                <code className="d-flex align-items-center gap-1">
                                  {iface.remoteIp || '—'}
                                  {iface.remoteIp && (
                                    <button
                                      className="btn btn-ghost-secondary btn-icon p-0"
                                      onClick={() => copyToClipboard(iface.remoteIp)}
                                      style={{ width: 20, height: 20 }}
                                    >
                                      <IconCopy size={12} />
                                    </button>
                                  )}
                                </code>
                              </td>
                              <td>
                                <div>
                                  {server ? (
                                    <div className="d-flex align-items-center">
                                      <IconServer size={14} className="text-muted me-1" />
                                      <span>{server.dns || server.ip}</span>
                                    </div>
                                  ) : iface.serverId ? (
                                    <span className="text-muted">{iface.serverId}</span>
                                  ) : (
                                    <span className="text-muted">—</span>
                                  )}
                                  {server2 && (
                                    <div className="d-flex align-items-center mt-1">
                                      <IconServer size={14} className="text-muted me-1" />
                                      <span className="text-muted small">{server2.dns || server2.ip}</span>
                                    </div>
                                  )}
                                </div>
                              </td>
                              <td className="text-end">
                                <div className="btn-list gap-1 mb-0 justify-content-end">
                                  <button
                                    className="btn btn-ghost-primary btn-icon btn-sm"
                                    onClick={() => handleEditInterface(iface)}
                                    title="Редактировать"
                                  >
                                    <IconEdit size={16} />
                                  </button>
                                  <button
                                    className="btn btn-ghost-danger btn-icon btn-sm"
                                    onClick={() => handleDeleteInterface(iface)}
                                    title="Удалить"
                                  >
                                    <IconTrash size={16} />
                                  </button>
                                </div>
                              </td>
                            </tr>
                          );
                        })}
                      </tbody>
                    </table>
                  </div>
                </div>
              )}
            </>
          )}

          {/* IP Pools Tab */}
          {activeTab === 'pools' && (
            <>
              {filteredPools.length === 0 ? (
                <div className="empty">
                  <div className="empty-img">
                    <IconDatabase size={48} />
                  </div>
                  <p className="empty-title">IP пулы не найдены</p>
                  <p className="empty-subtitle text-muted">
                    {hasActiveFilters 
                      ? 'Попробуйте изменить параметры фильтрации'
                      : 'Добавьте пулы IP-адресов для организации сетей'
                    }
                  </p>
                  {!hasActiveFilters && (
                    <div className="empty-action">
                      <button className="btn btn-primary" onClick={handleAddPool}>
                        <IconPlus size={16} className="me-2" />
                        Добавить IP пул
                      </button>
                    </div>
                  )}
                </div>
              ) : (
                <>
                  {/* Группировка по серверам */}
                  {(serverFilter || filteredPools.some(p => p.serverId)) && (() => {
                    const poolsByServer = {};
                    filteredPools.forEach(pool => {
                      const key = pool.serverId || '__unassigned__';
                      if (!poolsByServer[key]) {
                        poolsByServer[key] = [];
                      }
                      poolsByServer[key].push(pool);
                    });
                    
                    return Object.entries(poolsByServer)
                      .sort(([a], [b]) => {
                        if (a === '__unassigned__') return 1;
                        if (b === '__unassigned__') return -1;
                        return a.localeCompare(b);
                      })
                      .map(([serverId, pools]) => renderServerGroup(serverId, pools, 'pool'));
                  })()}
                  
                  {/* Если нет фильтра по серверу и все пулы без сервера - показываем без группировки */}
                  {!serverFilter && !filteredPools.some(p => p.serverId) && (
                    <div className="row row-cards">
                      {filteredPools.map(pool => (
                        <div key={pool.id} className="col-12 col-md-6 col-lg-6">
                          {renderPoolCard(pool)}
                        </div>
                      ))}
                    </div>
                  )}
                </>
              )}
            </>
          )}

          {/* IP Registry Tab */}
          {activeTab === 'ip-registry' && (
            <>
              <div className="mb-3">
                <div className="input-group">
                  <span className="input-group-text">
                    <IconSearch size={16} />
                  </span>
                  <input
                    type="text"
                    className="form-control"
                    placeholder="Поиск по IP адресу или имени интерфейса..."
                    value={ipRegistrySearch}
                    onChange={(e) => setIpRegistrySearch(e.target.value)}
                  />
                </div>
              </div>

              {filteredIpRegistry.length === 0 ? (
                <div className="empty">
                  <div className="empty-img">
                    <IconList size={48} />
                  </div>
                  <p className="empty-title">Реестр IP адресов пуст</p>
                  <p className="empty-subtitle text-muted">
                    {ipRegistrySearch
                      ? 'Попробуйте изменить поисковый запрос'
                      : 'Добавьте интерфейсы, чтобы увидеть используемые IP адреса'}
                  </p>
                </div>
              ) : (
                <div className="card">
                  <div className="table-responsive">
                    <table className="table table-vcenter card-table">
                      <thead>
                        <tr>
                          <th>IP адрес</th>
                          <th>Тип</th>
                          <th>Сервер</th>
                          <th>PTR зона</th>
                          <th>Интерфейс</th>
                          <th className="text-end">Действия</th>
                        </tr>
                      </thead>
                      <tbody>
                        {filteredIpRegistry.map((item, idx) => (
                          <tr key={`${item.ip}-${item.type}-${item.interface.id}-${idx}`} className={item.hasConflict ? 'table-danger' : ''}>
                            <td>
                              <div className="d-flex align-items-center">
                                <code className="fw-bold">{item.ip}</code>
                                {item.hasConflict && (
                                  <span className="badge bg-danger ms-2" title="Конфликт: IP используется в нескольких интерфейсах">
                                    Конфликт
                                  </span>
                                )}
                              </div>
                            </td>
                            <td>
                              <span className={`badge ${item.type === 'localIp' ? 'bg-info-lt text-info' : 'bg-success-lt text-success'}`}>
                                {item.type === 'localIp' ? 'Local' : 'Remote'}
                              </span>
                            </td>
                            <td>
                              <div className="d-flex align-items-center">
                                <IconServer size={14} className="text-muted me-1" />
                                <span>{item.serverName}</span>
                              </div>
                            </td>
                            <td>
                              <code className="text-muted">{item.ptrZone}</code>
                            </td>
                            <td>
                              <div className="d-flex align-items-center gap-2">
                                <span>{item.interfaceName}</span>
                                <button
                                  className="btn btn-ghost-primary btn-icon btn-sm"
                                  onClick={() => handleEditInterface(item.interface)}
                                  title="Редактировать интерфейс"
                                >
                                  <IconEdit size={14} />
                                </button>
                              </div>
                            </td>
                            <td className="text-end">
                              <button
                                className="btn btn-ghost-primary btn-icon btn-sm"
                                onClick={() => {
                                  navigator.clipboard.writeText(item.ip).then(() => {
                                    notify.success('IP адрес скопирован');
                                  }).catch(() => {
                                    notify.error('Не удалось скопировать IP адрес');
                                  });
                                }}
                                title="Копировать IP адрес"
                              >
                                <IconCopy size={16} />
                              </button>
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                </div>
              )}
            </>
          )}
        </>
      )}

      {/* Gateway Modal */}
      <FormModal
        show={gatewayModalOpen}
        onClose={() => { setGatewayModalOpen(false); setEditingGateway(null); }}
        onSubmit={() => editingGateway && handleSaveGateway(editingGateway)}
        title={gatewayModalMode === 'add' ? 'Добавить Gateway' : 'Редактировать Gateway'}
        submitLabel={gatewayModalMode === 'add' ? 'Добавить' : 'Сохранить'}
        submitIcon={gatewayModalMode === 'add' ? IconPlus : IconEdit}
        size="lg"
      >
        {editingGateway && (
          <div className="row g-3">
            <div className="col-12">
              <label className="form-label required">Сервер</label>
              <ServerAutocompleteInput
                value={editingGateway.serverId}
                onChange={(val) => setEditingGateway({ ...editingGateway, serverId: val })}
                servers={servers}
                placeholder="Выберите сервер..."
              />
              <div className="form-text">
                Провайдер будет автоматически взят из данных сервера
              </div>
            </div>
            <div className="col-md-6">
              <FormField
                label="IP адрес"
                name="ip"
                value={editingGateway.ip}
                onChange={(val) => setEditingGateway({ ...editingGateway, ip: val })}
                placeholder="94.142.140.1"
                required
              />
              <div className="form-text">
                IP адрес является главным идентификатором gateway
              </div>
            </div>
            <div className="col-md-6">
              <FormField
                label="Название (комментарий)"
                name="description"
                value={editingGateway.description}
                onChange={(val) => setEditingGateway({ ...editingGateway, description: val })}
                placeholder="SWE-IHOR или Основной выход через Cloudflare"
              />
              <div className="form-text">
                Название gateway для удобства (отображается в фильтрах)
              </div>
            </div>
            <div className="col-md-6">
              <FormField
                label="Тип gateway"
                name="type"
                type="select"
                value={editingGateway.type}
                onChange={(val) => setEditingGateway({ ...editingGateway, type: val, parentGateways: val === 'direct' ? [] : (editingGateway.parentGateways || []) })}
                options={GATEWAY_TYPES.map(t => ({ value: t.value, label: `${t.label} - ${t.description}` }))}
                required
              />
            </div>
            <div className="col-md-6">
              <FormField
                label="Страна"
                name="country"
                value={editingGateway.country}
                onChange={(val) => setEditingGateway({ ...editingGateway, country: val.toUpperCase().slice(0, 2) })}
                placeholder="SWE"
              />
              <div className="form-text">2-буквенный код страны (ISO 3166-1 alpha-2)</div>
            </div>
            {editingGateway.type === 'recursive' && (
              <div className="col-12">
                <label className="form-label">Родительские gateway или интерфейсы</label>
                <div className="d-flex flex-column gap-2">
                  {(editingGateway.parentGateways || []).map((parent, index) => {
                    const parentInfo = getParentGateway(parent.id);
                    return (
                      <div key={index} className="card card-sm border">
                        <div className="card-body p-2">
                          <div className="row g-2 align-items-center">
                            <div className="col-md-8">
                              <GatewayAutocompleteInput
                                value={parent.id}
                                onChange={(val) => {
                                  const newParents = [...(editingGateway.parentGateways || [])];
                                  newParents[index] = { ...newParents[index], id: val };
                                  setEditingGateway({ ...editingGateway, parentGateways: newParents });
                                }}
                                gateways={config.gateways}
                                interfaces={config.tunnelInterfaces}
                                excludeGatewayId={editingGateway.id}
                                placeholder="Выберите родительский gateway или интерфейс..."
                              />
                            </div>
                            <div className="col-md-3">
                              <FormField
                                label="Distance"
                                name="distance"
                                type="number"
                                value={parent.distance || ''}
                                onChange={(val) => {
                                  const newParents = [...(editingGateway.parentGateways || [])];
                                  newParents[index] = { ...newParents[index], distance: val ? parseInt(val) : undefined };
                                  setEditingGateway({ ...editingGateway, parentGateways: newParents });
                                }}
                                placeholder="1"
                              />
                            </div>
                            <div className="col-md-1 d-flex align-items-end">
                              <button
                                type="button"
                                className="btn btn-outline-danger btn-sm"
                                onClick={() => {
                                  const newParents = (editingGateway.parentGateways || []).filter((_, i) => i !== index);
                                  setEditingGateway({ ...editingGateway, parentGateways: newParents });
                                }}
                                title="Удалить"
                              >
                                <IconTrash size={16} />
                              </button>
                            </div>
                          </div>
                          {parentInfo && (
                            <div className="mt-2 small text-muted">
                              {parentInfo.parentType === 'interface' 
                                ? `Интерфейс ${parentInfo.name || parentInfo.interfaceType || 'interface'} (${parentInfo.remoteIp || '—'})`
                                : `Gateway ${parentInfo.ip || '—'}`
                              }
                            </div>
                          )}
                        </div>
                      </div>
                    );
                  })}
                  <button
                    type="button"
                    className="btn btn-outline-primary btn-sm"
                    onClick={() => {
                      const newParents = [...(editingGateway.parentGateways || []), { id: '', distance: undefined }];
                      setEditingGateway({ ...editingGateway, parentGateways: newParents });
                    }}
                  >
                    <IconPlus size={16} className="me-1" />
                    Добавить родительский gateway
                  </button>
                </div>
                <div className="form-text">
                  Рекурсивный gateway может ссылаться на несколько прямых gateway или интерфейсов. Distance определяет приоритет маршрута (меньше = выше приоритет).
                </div>
              </div>
            )}
            {editingGateway.serverId && (() => {
              const server = getServerInfo(editingGateway.serverId);
              return server ? (
                <div className="col-12">
                  <div className="alert alert-info mb-0">
                    <div className="d-flex align-items-center">
                      <IconServer size={16} className="me-2" />
                      <div>
                        <strong>{server.dns || server.ip}</strong>
                        {server.provider && <span className="ms-2">• {server.provider}</span>}
                        {server.country && <span className="ms-2">• {countryToFlag(server.country)} {server.country}</span>}
                      </div>
                    </div>
                  </div>
                </div>
              ) : null;
            })()}
          </div>
        )}
      </FormModal>

      {/* Interface Modal */}
      <FormModal
        show={interfaceModalOpen}
        onClose={() => { setInterfaceModalOpen(false); setEditingInterface(null); }}
        onSubmit={() => editingInterface && handleSaveInterface(editingInterface)}
        title={interfaceModalMode === 'add' ? 'Добавить интерфейс' : 'Редактировать интерфейс'}
        submitLabel={interfaceModalMode === 'add' ? 'Добавить' : 'Сохранить'}
        submitIcon={interfaceModalMode === 'add' ? IconPlus : IconEdit}
        size="lg"
      >
        {editingInterface && (
          <div className="row g-3">
            <div className="col-12">
              <label className="form-label">Сервер</label>
              <ServerAutocompleteInput
                value={editingInterface.serverId}
                onChange={(val) => setEditingInterface({ ...editingInterface, serverId: val })}
                servers={servers}
                placeholder="Выберите сервер..."
              />
              <div className="form-text">Интерфейс будет привязан к выбранному серверу</div>
            </div>
            <div className="col-md-6">
              <FormField
                label="Имя интерфейса (сервер 1)"
                name="name"
                value={editingInterface.name}
                onChange={(val) => setEditingInterface({ ...editingInterface, name: val })}
                placeholder="gre-tunnel1"
                required
              />
            </div>
            {editingInterface.serverId2 && (
              <div className="col-md-6">
                <FormField
                  label="Имя интерфейса (сервер 2)"
                  name="name2"
                  value={editingInterface.name2 || ''}
                  onChange={(val) => setEditingInterface({ ...editingInterface, name2: val })}
                  placeholder="gre-tunnel2"
                />
                <div className="form-text">Если не указано, будет использовано имя с сервера 1</div>
              </div>
            )}
            <div className="col-md-6">
              <FormField
                label="Тип"
                name="type"
                type="select"
                value={editingInterface.type}
                onChange={(val) => setEditingInterface({ ...editingInterface, type: val, ipsecPasswordId: (val !== 'IPSec' && val !== 'GRE') ? '' : editingInterface.ipsecPasswordId })}
                options={INTERFACE_TYPES}
              />
            </div>
            {(editingInterface.type === 'IPSec' || editingInterface.type === 'GRE') && (
              <div className="col-md-6">
                <label className="form-label">IPSec пароль</label>
                <div className="input-group">
                  <select
                    className="form-select"
                    value={editingInterface.ipsecPasswordId || ''}
                    onChange={(e) => setEditingInterface({ ...editingInterface, ipsecPasswordId: e.target.value })}
                  >
                    <option value="">Не выбран</option>
                    {ipsecPasswords.map(pwd => (
                      <option key={pwd.id} value={pwd.id}>
                        {pwd.name} {pwd.description ? `(${pwd.description})` : ''}
                      </option>
                    ))}
                  </select>
                  <button
                    type="button"
                    className="btn btn-outline-primary"
                    onClick={() => {
                      setIpsecPasswordModalMode('add');
                      setEditingIpsecPassword({ name: '', password: '', description: '' });
                      setIpsecPasswordModalOpen(true);
                    }}
                    title="Создать новый IPSec пароль"
                  >
                    <IconPlus size={16} />
                  </button>
                </div>
                <div className="form-text">
                  Выберите сохраненный IPSec пароль или создайте новый (опционально для GRE)
                </div>
              </div>
            )}
            <div className="col-md-6">
              <label className="form-label">IP пул</label>
              <select
                className="form-select"
                value={editingInterface.ipPoolId || ''}
                onChange={(e) => setEditingInterface({ ...editingInterface, ipPoolId: e.target.value || '' })}
              >
                <option value="">Автоматический подбор (RFC 1918)</option>
                {config.ipPools?.map(pool => (
                  <option key={pool.id} value={pool.id}>
                    {pool.name} ({pool.cidr}) {pool.description ? `- ${pool.description}` : ''}
                  </option>
                ))}
              </select>
              <div className="form-text">
                Выберите IP пул для подбора адресов или оставьте автоматический подбор
              </div>
            </div>
            <div className="col-md-6">
              <FormField
                label="MTU"
                name="mtu"
                value={editingInterface.mtu || ''}
                onChange={(val) => setEditingInterface({ ...editingInterface, mtu: val })}
                placeholder="1500"
                type="number"
              />
              <div className="form-text">Максимальный размер передаваемого пакета (опционально)</div>
            </div>
            <div className="col-md-3">
              <label className="form-label">Local IP</label>
              <div className="input-group">
                <input
                  type="text"
                  className="form-control"
                  value={editingInterface.localIp || ''}
                  onChange={(e) => setEditingInterface({ ...editingInterface, localIp: e.target.value })}
                  placeholder="10.10.0.1"
                />
                <button
                  type="button"
                  className="btn btn-outline-primary"
                  onClick={handleSuggestLocalIp}
                  title="Подобрать свободный IP из приватного диапазона"
                >
                  <IconWand size={16} />
                </button>
              </div>
              {editingInterface.localIp && (() => {
                const conflicts = checkInterfaceIpConflict(
                  { localIp: editingInterface.localIp },
                  interfaceModalMode === 'edit' ? editingInterface.id : null
                ).filter(c => c.type === 'localIp');
                if (conflicts.length > 0) {
                  return (
                    <div className="form-text text-danger">
                      ⚠️ Этот IP уже используется в интерфейсе "{conflicts[0].conflictingInterface.name || conflicts[0].conflictingInterface.id}"
                    </div>
                  );
                }
                return null;
              })()}
            </div>
            <div className="col-md-3">
              <label className="form-label">Remote IP</label>
              <div className="input-group">
                <input
                  type="text"
                  className="form-control"
                  value={editingInterface.remoteIp || ''}
                  onChange={(e) => setEditingInterface({ ...editingInterface, remoteIp: e.target.value })}
                  placeholder="10.10.0.2"
                />
                <button
                  type="button"
                  className="btn btn-outline-primary"
                  onClick={handleSuggestRemoteIp}
                  title="Подобрать свободный IP из приватного диапазона (в той же сети /30 что и Local IP)"
                >
                  <IconWand size={16} />
                </button>
              </div>
              {editingInterface.remoteIp && (() => {
                const conflicts = checkInterfaceIpConflict(
                  { remoteIp: editingInterface.remoteIp },
                  interfaceModalMode === 'edit' ? editingInterface.id : null
                ).filter(c => c.type === 'remoteIp');
                if (conflicts.length > 0) {
                  return (
                    <div className="form-text text-danger">
                      ⚠️ Этот IP уже используется в интерфейсе "{conflicts[0].conflictingInterface.name || conflicts[0].conflictingInterface.id}"
                    </div>
                  );
                }
                return null;
              })()}
            </div>
            <div className="col-12">
              <label className="form-label">Второй сервер (опционально)</label>
              <ServerAutocompleteInput
                value={editingInterface.serverId2 || ''}
                onChange={(val) => setEditingInterface({ ...editingInterface, serverId2: val })}
                servers={servers.filter(s => s.id !== editingInterface.serverId && s.ip !== editingInterface.serverId)}
                placeholder="Выберите второй сервер (для понимания связи между серверами)..."
              />
              <div className="form-text">
                Укажите второй сервер, если интерфейс связывает два сервера
              </div>
            </div>
            {editingInterface.serverId && (() => {
              const server = getServerInfo(editingInterface.serverId);
              return server ? (
                <div className="col-12">
                  <div className="card card-sm border">
                    <div className="card-body p-2">
                      <div className="d-flex align-items-center">
                        <IconServer size={16} className="text-muted me-2" />
                        <span className="fw-medium text-muted me-2">Сервер 1:</span>
                        <span className="me-2">{server.dns || server.ip}</span>
                        {server.provider && (
                          <>
                            <span className="text-muted me-2">•</span>
                            <span className="me-2">{server.provider}</span>
                          </>
                        )}
                        {server.country && (
                          <>
                            <span className="text-muted me-2">•</span>
                            <span>{countryToFlag(server.country)}</span>
                            <span className="ms-1">{server.country}</span>
                          </>
                        )}
                      </div>
                    </div>
                  </div>
                </div>
              ) : null;
            })()}
            {editingInterface.serverId2 && (() => {
              const server2 = getServerInfo(editingInterface.serverId2);
              return server2 ? (
                <div className="col-12">
                  <div className="card card-sm border">
                    <div className="card-body p-2">
                      <div className="d-flex align-items-center">
                        <IconServer size={16} className="text-muted me-2" />
                        <span className="fw-medium text-muted me-2">Сервер 2:</span>
                        <span className="me-2">{server2.dns || server2.ip}</span>
                        {server2.provider && (
                          <>
                            <span className="text-muted me-2">•</span>
                            <span className="me-2">{server2.provider}</span>
                          </>
                        )}
                        {server2.country && (
                          <>
                            <span className="text-muted me-2">•</span>
                            <span>{countryToFlag(server2.country)}</span>
                            <span className="ms-1">{server2.country}</span>
                          </>
                        )}
                      </div>
                    </div>
                  </div>
                </div>
              ) : null;
            })()}
          </div>
        )}
      </FormModal>

      {/* Interface Template Modal */}
      <FormModal
        show={interfaceTemplateModalOpen}
        onClose={() => { 
          setInterfaceTemplateModalOpen(false);
          setTemplateServer1('');
          setTemplateServer2('');
          setTemplateType('GRE');
          setTemplateNamePrefix('');
          setTemplateName1('');
          setTemplateName2('');
          setTemplateIpsecPasswordId('');
          setTemplateIpPoolId('');
          setTemplateMtu('');
          setTemplateTunnelCount(1);
          setTemplateServerPairs([]);
        }}
        onSubmit={handleCreateInterfaceFromTemplate}
        title="Создать интерфейс из шаблона"
        submitLabel={templateTunnelCount > 1 ? `Создать ${templateTunnelCount} туннелей` : "Создать интерфейс"}
        submitIcon={IconSparkles}
        size="lg"
      >
        <div className="row g-3">
          <div className="col-md-6">
            <label className="form-label required">Количество туннелей</label>
            <input
              type="number"
              className="form-control"
              value={templateTunnelCount}
              onChange={(e) => {
                const value = parseInt(e.target.value) || 1;
                const newCount = Math.max(1, Math.min(100, value));
                setTemplateTunnelCount(newCount);
                // Синхронизируем количество пар
                if (newCount > templateServerPairs.length) {
                  const newPairs = [...templateServerPairs];
                  while (newPairs.length < newCount) {
                    newPairs.push({
                      server1: '',
                      server2: '',
                      name1: '',
                      name2: '',
                      ipsecPasswordId: '',
                      ipPoolId: ''
                    });
                  }
                  setTemplateServerPairs(newPairs);
                } else if (newCount < templateServerPairs.length) {
                  setTemplateServerPairs(templateServerPairs.slice(0, newCount));
                }
              }}
              min="1"
              max="100"
            />
            <div className="form-text">
              {templateTunnelCount > 1 
                ? `Настройте ${templateTunnelCount} пар серверов ниже`
                : 'Сколько туннелей создать между выбранными серверами (1-100)'}
            </div>
          </div>
          <div className="col-md-6">
            <label className="form-label required">Тип интерфейса</label>
            <FormField
              name="type"
              type="select"
              value={templateType}
              onChange={(val) => setTemplateType(val)}
              options={INTERFACE_TYPES}
            />
          </div>
          <div className="col-md-6">
            <label className="form-label">Префикс имени (опционально)</label>
            <input
              type="text"
              className="form-control"
              value={templateNamePrefix}
              onChange={(e) => setTemplateNamePrefix(e.target.value)}
              placeholder="tunnel"
            />
            <div className="form-text">Будет добавлен перед именем интерфейса</div>
          </div>
          {(templateTunnelCount === 1) && (
            <>
              <div className="col-md-6">
                <label className="form-label required">Сервер 1</label>
                <ServerAutocompleteInput
                  value={templateServer1}
                  onChange={(val) => setTemplateServer1(val)}
                  servers={servers.filter(s => s.id !== templateServer2 && s.ip !== templateServer2)}
                  placeholder="Выберите первый сервер..."
                />
                {templateServer1 && (() => {
                  const server1 = getServerInfo(templateServer1);
                  return server1 ? (
                    <div className="form-text">
                      {server1.dns || server1.ip}
                      {server1.country && ` • ${countryToFlag(server1.country)} ${server1.country}`}
                    </div>
                  ) : null;
                })()}
              </div>
              <div className="col-md-6">
                <label className="form-label required">Сервер 2</label>
                <ServerAutocompleteInput
                  value={templateServer2}
                  onChange={(val) => setTemplateServer2(val)}
                  servers={servers.filter(s => s.id !== templateServer1 && s.ip !== templateServer1)}
                  placeholder="Выберите второй сервер..."
                />
                {templateServer2 && (() => {
                  const server2 = getServerInfo(templateServer2);
                  return server2 ? (
                    <div className="form-text">
                      {server2.dns || server2.ip}
                      {server2.country && ` • ${countryToFlag(server2.country)} ${server2.country}`}
                    </div>
                  ) : null;
                })()}
              </div>
            </>
          )}
          {templateTunnelCount > 1 && (
            <div className="col-12">
              <label className="form-label required">Пары серверов</label>
              <div className="d-flex flex-column gap-3">
                {Array.from({ length: templateTunnelCount }).map((_, index) => {
                  const pair = templateServerPairs[index] || {
                    server1: '',
                    server2: '',
                    name1: '',
                    name2: '',
                    ipsecPasswordId: '',
                    ipPoolId: ''
                  };
                  
                  const updatePair = (updates) => {
                    const newPairs = [...templateServerPairs];
                    while (newPairs.length < templateTunnelCount) {
                      newPairs.push({
                        server1: '',
                        server2: '',
                        name1: '',
                        name2: '',
                        ipsecPasswordId: '',
                        ipPoolId: ''
                      });
                    }
                    newPairs[index] = { ...pair, ...updates };
                    setTemplateServerPairs(newPairs.slice(0, templateTunnelCount));
                  };
                  
                  const server1 = getServerInfo(pair.server1);
                  const server2 = getServerInfo(pair.server2);
                  
                  return (
                    <div key={index} className="card border">
                      <div className="card-header bg-light d-flex justify-content-between align-items-center">
                        <span className="fw-semibold">Туннель {index + 1}</span>
                      </div>
                      <div className="card-body">
                        <div className="row g-3">
                          <div className="col-md-6">
                            <label className="form-label required">Сервер 1</label>
                            <ServerAutocompleteInput
                              value={pair.server1}
                              onChange={(val) => updatePair({ server1: val })}
                              servers={servers.filter(s => s.id !== pair.server2 && s.ip !== pair.server2)}
                              placeholder="Выберите первый сервер..."
                            />
                            {server1 && (
                              <div className="form-text">
                                {server1.dns || server1.ip}
                                {server1.country && ` • ${countryToFlag(server1.country)} ${server1.country}`}
                              </div>
                            )}
                          </div>
                          <div className="col-md-6">
                            <label className="form-label required">Сервер 2</label>
                            <ServerAutocompleteInput
                              value={pair.server2}
                              onChange={(val) => updatePair({ server2: val })}
                              servers={servers.filter(s => s.id !== pair.server1 && s.ip !== pair.server1)}
                              placeholder="Выберите второй сервер..."
                            />
                            {server2 && (
                              <div className="form-text">
                                {server2.dns || server2.ip}
                                {server2.country && ` • ${countryToFlag(server2.country)} ${server2.country}`}
                              </div>
                            )}
                          </div>
                          <div className="col-md-6">
                            <label className="form-label">Имя интерфейса (сервер 1)</label>
                            <input
                              type="text"
                              className="form-control"
                              value={pair.name1 || ''}
                              onChange={(e) => updatePair({ name1: e.target.value })}
                              placeholder={server1 && server2 ? generateInterfaceName(server1, server2, templateType, templateNamePrefix) : ''}
                            />
                            <div className="form-text">Оставьте пустым для автогенерации</div>
                          </div>
                          <div className="col-md-6">
                            <label className="form-label">Имя интерфейса (сервер 2)</label>
                            <input
                              type="text"
                              className="form-control"
                              value={pair.name2 || ''}
                              onChange={(e) => updatePair({ name2: e.target.value })}
                              placeholder={server2 && server1 ? generateInterfaceName(server2, server1, templateType, templateNamePrefix) : ''}
                            />
                            <div className="form-text">Оставьте пустым для автогенерации</div>
                          </div>
                          {(templateType === 'IPSec' || templateType === 'GRE') && (
                            <div className="col-md-6">
                              <label className="form-label">IPSec пароль (опционально)</label>
                              <select
                                className="form-select"
                                value={pair.ipsecPasswordId || ''}
                                onChange={(e) => updatePair({ ipsecPasswordId: e.target.value })}
                              >
                                <option value="">Использовать глобальный ({templateIpsecPasswordId ? ipsecPasswords.find(p => p.id === templateIpsecPasswordId)?.name || 'выбран' : 'не выбран'})</option>
                                {ipsecPasswords.map(pwd => (
                                  <option key={pwd.id} value={pwd.id}>
                                    {pwd.name} {pwd.description ? `(${pwd.description})` : ''}
                                  </option>
                                ))}
                              </select>
                            </div>
                          )}
                          <div className="col-md-6">
                            <label className="form-label">IP пул (опционально)</label>
                            <select
                              className="form-select"
                              value={pair.ipPoolId || ''}
                              onChange={(e) => updatePair({ ipPoolId: e.target.value })}
                            >
                              <option value="">Использовать глобальный ({templateIpPoolId ? config.ipPools?.find(p => p.id === templateIpPoolId)?.name || 'выбран' : 'автоматический'})</option>
                              {config.ipPools?.map(pool => (
                                <option key={pool.id} value={pool.id}>
                                  {pool.name} ({pool.cidr}) {pool.description ? `- ${pool.description}` : ''}
                                </option>
                              ))}
                            </select>
                          </div>
                        </div>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          )}
          {(templateTunnelCount === 1) && (
            <>
              <div className="col-md-6">
                <label className="form-label">Имя интерфейса (сервер 1)</label>
                <input
                  type="text"
                  className="form-control"
                  value={templateName1}
                  onChange={(e) => setTemplateName1(e.target.value)}
                  placeholder={templateServer1 && templateServer2 ? (() => {
                    const s1 = getServerInfo(templateServer1);
                    const s2 = getServerInfo(templateServer2);
                    return s1 && s2 ? generateInterfaceName(s1, s2, templateType, templateNamePrefix) : '';
                  })() : ''}
                />
                <div className="form-text">Оставьте пустым для автогенерации</div>
              </div>
              <div className="col-md-6">
                <label className="form-label">Имя интерфейса (сервер 2)</label>
                <input
                  type="text"
                  className="form-control"
                  value={templateName2}
                  onChange={(e) => setTemplateName2(e.target.value)}
                  placeholder={templateServer1 && templateServer2 ? (() => {
                    const s1 = getServerInfo(templateServer1);
                    const s2 = getServerInfo(templateServer2);
                    return s1 && s2 ? generateInterfaceName(s2, s1, templateType, templateNamePrefix) : '';
                  })() : ''}
                />
                <div className="form-text">Оставьте пустым для автогенерации</div>
              </div>
            </>
          )}
          {(templateType === 'IPSec' || templateType === 'GRE') && (
            <div className="col-12">
              <label className="form-label">IPSec пароль (глобальный, используется если не указан для пары)</label>
              <div className="input-group">
                <select
                  className="form-select"
                  value={templateIpsecPasswordId}
                  onChange={(e) => setTemplateIpsecPasswordId(e.target.value)}
                >
                  <option value="">Не выбран</option>
                  {ipsecPasswords.map(pwd => (
                    <option key={pwd.id} value={pwd.id}>
                      {pwd.name} {pwd.description ? `(${pwd.description})` : ''}
                    </option>
                  ))}
                </select>
                <button
                  type="button"
                  className="btn btn-outline-primary"
                  onClick={() => {
                    setIpsecPasswordModalMode('add');
                    setEditingIpsecPassword({ name: '', password: '', description: '' });
                    setIpsecPasswordModalOpen(true);
                  }}
                  title="Создать новый IPSec пароль"
                >
                  <IconPlus size={16} />
                </button>
              </div>
              <div className="form-text">
                Выберите сохраненный IPSec пароль или создайте новый (опционально для GRE). Будет использован для всех туннелей, если не указан индивидуально.
              </div>
            </div>
          )}
          <div className="col-12">
            <label className="form-label">IP пул (глобальный, используется если не указан для пары)</label>
            <select
              className="form-select"
              value={templateIpPoolId}
              onChange={(e) => setTemplateIpPoolId(e.target.value)}
            >
              <option value="">Автоматический подбор (RFC 1918)</option>
              {config.ipPools?.map(pool => (
                <option key={pool.id} value={pool.id}>
                  {pool.name} ({pool.cidr}) {pool.description ? `- ${pool.description}` : ''}
                </option>
              ))}
            </select>
            <div className="form-text">
              Выберите IP пул для подбора адресов или оставьте автоматический подбор. Будет использован для всех туннелей, если не указан индивидуально.
            </div>
          </div>
          <div className="col-md-6">
            <label className="form-label">MTU (глобальный, используется если не указан для пары)</label>
            <input
              type="number"
              className="form-control"
              value={templateMtu}
              onChange={(e) => setTemplateMtu(e.target.value)}
              placeholder="1500"
            />
            <div className="form-text">
              Максимальный размер передаваемого пакета (опционально). Будет использован для всех туннелей, если не указан индивидуально.
            </div>
          </div>
          {templateTunnelCount === 1 && templateServer1 && templateServer2 && templateServer1 !== templateServer2 && (() => {
            const server1 = getServerInfo(templateServer1);
            const server2 = getServerInfo(templateServer2);
            if (!server1 || !server2) return null;
            
            const autoName1 = generateInterfaceName(server1, server2, templateType, templateNamePrefix);
            const autoName2 = generateInterfaceName(server2, server1, templateType, templateNamePrefix);
            const previewName1 = (templateName1.trim() || autoName1).toUpperCase();
            const previewName2 = (templateName2.trim() || autoName2).toUpperCase();
            const previewLocalIp = generateFreePrivateIp(null, false, null, templateIpPoolId || null);
            const previewRemoteIp = previewLocalIp ? generateFreePrivateIp(null, true, previewLocalIp, templateIpPoolId || null) : null;
            
            return (
              <>
                <div className="col-12">
                  <div className="card card-sm border">
                    <div className="card-header bg-light">
                      <strong>Предпросмотр интерфейса:</strong>
                    </div>
                    <div className="card-body">
                      <div className="row">
                        <div className="col-md-6">
                          <div className="mb-2">
                            <strong>Сервер 1 ({server1.dns || server1.ip}):</strong>
                            <div className="ms-2">
                              <div>Имя: {previewName1}</div>
                              <div>Local IP: {previewLocalIp || '—'}</div>
                            </div>
                          </div>
                        </div>
                        <div className="col-md-6">
                          <div className="mb-2">
                            <strong>Сервер 2 ({server2.dns || server2.ip}):</strong>
                            <div className="ms-2">
                              <div>Имя: {previewName2}</div>
                              <div>Local IP: {previewRemoteIp || '—'}</div>
                            </div>
                          </div>
                        </div>
                        {previewLocalIp && previewRemoteIp && (
                          <div className="col-12 text-center">
                            <IconArrowsRightLeft size={20} className="text-muted" />
                            <span className="ms-2 text-muted">{previewLocalIp} ↔ {previewRemoteIp}</span>
                          </div>
                        )}
                      </div>
                    </div>
                  </div>
                </div>
              </>
            );
          })()}
          {templateTunnelCount > 1 && templateServerPairs.length === templateTunnelCount && (
            <div className="col-12">
              <label className="form-label">Предпросмотр туннелей:</label>
              <div className="d-flex flex-column gap-3">
                {templateServerPairs.map((pair, index) => {
                  const server1 = getServerInfo(pair.server1);
                  const server2 = getServerInfo(pair.server2);
                  if (!server1 || !server2 || !pair.server1 || !pair.server2 || pair.server1 === pair.server2) {
                    return null;
                  }
                  
                  const baseName1 = generateInterfaceName(server1, server2, templateType, templateNamePrefix);
                  const baseName2 = generateInterfaceName(server2, server1, templateType, templateNamePrefix);
                  const previewName1 = (pair.name1?.trim() || baseName1).toUpperCase();
                  const previewName2 = (pair.name2?.trim() || baseName2).toUpperCase();
                  
                  // Используем настройки из пары или глобальные для предпросмотра
                  const pairIpPoolId = pair.ipPoolId || templateIpPoolId;
                  
                  // Генерируем предпросмотр IP (используем временный Set для предпросмотра)
                  const previewUsedIps = new Set(getAllUsedIpsSet);
                  // Добавляем IP из предыдущих туннелей в предпросмотре
                  for (let i = 0; i < index; i++) {
                    const prevPair = templateServerPairs[i];
                    if (prevPair.server1 && prevPair.server2) {
                      const prevPairIpPoolId = prevPair.ipPoolId || templateIpPoolId;
                      const prevPreviewLocal = generateFreePrivateIp(null, false, null, prevPairIpPoolId || null, previewUsedIps);
                      if (prevPreviewLocal) {
                        previewUsedIps.add(prevPreviewLocal);
                        const prevPreviewRemote = generateFreePrivateIp(null, true, prevPreviewLocal, prevPairIpPoolId || null, previewUsedIps);
                        if (prevPreviewRemote && prevPreviewRemote !== prevPreviewLocal) {
                          previewUsedIps.add(prevPreviewRemote);
                        }
                      }
                    }
                  }
                  
                  // Генерируем IP для текущего туннеля
                  let previewLocalIp = generateFreePrivateIp(null, false, null, pairIpPoolId || null, previewUsedIps);
                  let previewRemoteIp = null;
                  
                  if (previewLocalIp) {
                    // Генерируем Remote IP на основе Local IP
                    previewRemoteIp = generateFreePrivateIp(null, true, previewLocalIp, pairIpPoolId || null, previewUsedIps);
                    
                    // Если Remote IP не сгенерировался или совпадает с Local IP, пробуем найти другую пару
                    if (!previewRemoteIp || previewRemoteIp === previewLocalIp) {
                      // Добавляем текущий Local IP в использованные и пробуем найти другую пару
                      previewUsedIps.add(previewLocalIp);
                      const altPreviewLocalIp = generateFreePrivateIp(null, false, null, pairIpPoolId || null, previewUsedIps);
                      if (altPreviewLocalIp && altPreviewLocalIp !== previewLocalIp) {
                        const altPreviewRemoteIp = generateFreePrivateIp(null, true, altPreviewLocalIp, pairIpPoolId || null, previewUsedIps);
                        if (altPreviewRemoteIp && altPreviewRemoteIp !== altPreviewLocalIp) {
                          previewLocalIp = altPreviewLocalIp;
                          previewRemoteIp = altPreviewRemoteIp;
                        } else {
                          // Если все равно не получилось, удаляем альтернативный Local IP
                          previewUsedIps.delete(altPreviewLocalIp);
                        }
                      }
                    }
                  }
                  
                  return (
                    <div key={index} className="card card-sm border">
                      <div className="card-header bg-light">
                        <strong>Туннель {index + 1}:</strong>
                      </div>
                      <div className="card-body">
                        <div className="row">
                          <div className="col-md-6">
                            <div className="mb-2">
                              <strong>Сервер 1 ({server1.dns || server1.ip}):</strong>
                              <div className="ms-2">
                                <div>Имя: {previewName1}</div>
                                <div>Local IP: {previewLocalIp || '—'}</div>
                              </div>
                            </div>
                          </div>
                          <div className="col-md-6">
                            <div className="mb-2">
                              <strong>Сервер 2 ({server2.dns || server2.ip}):</strong>
                              <div className="ms-2">
                                <div>Имя: {previewName2}</div>
                                <div>Local IP: {previewRemoteIp || '—'}</div>
                              </div>
                            </div>
                          </div>
                          {previewLocalIp && previewRemoteIp && (
                            <div className="col-12 text-center">
                              <IconArrowsRightLeft size={20} className="text-muted" />
                              <span className="ms-2 text-muted">{previewLocalIp} ↔ {previewRemoteIp}</span>
                            </div>
                          )}
                        </div>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>
          )}
        </div>
      </FormModal>

      {/* IPSec Password Modal */}
      <FormModal
        show={ipsecPasswordModalOpen}
        onClose={() => { 
          setIpsecPasswordModalOpen(false); 
          setEditingIpsecPassword(null); 
        }}
        onSubmit={handleSaveIpsecPassword}
        title={ipsecPasswordModalMode === 'add' ? 'Добавить IPSec пароль' : 'Редактировать IPSec пароль'}
        submitLabel={ipsecPasswordModalMode === 'add' ? 'Создать' : 'Сохранить'}
        submitIcon={ipsecPasswordModalMode === 'add' ? IconPlus : IconEdit}
      >
        {editingIpsecPassword && (
          <div className="row g-3">
            <div className="col-12">
              <FormField
                label="Название"
                name="name"
                value={editingIpsecPassword.name}
                onChange={(val) => setEditingIpsecPassword({ ...editingIpsecPassword, name: val })}
                placeholder="Основной IPSec пароль"
                required
              />
            </div>
            <div className="col-12">
              <FormField
                label="Пароль"
                name="password"
                type="password"
                value={editingIpsecPassword.password}
                onChange={(val) => setEditingIpsecPassword({ ...editingIpsecPassword, password: val })}
                placeholder="Введите пароль"
                required
              />
              <div className="form-text">Пароль будет зашифрован перед сохранением в S3</div>
            </div>
            <div className="col-12">
              <FormField
                label="Описание"
                name="description"
                value={editingIpsecPassword.description || ''}
                onChange={(val) => setEditingIpsecPassword({ ...editingIpsecPassword, description: val })}
                placeholder="Описание использования пароля"
              />
            </div>
          </div>
        )}
      </FormModal>

      {/* IPSec Passwords List Modal */}
      {ipsecPasswordsListModalOpen && (
        <div className="modal show d-block" style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
          <div className="modal-dialog modal-lg">
            <div className="modal-content">
              <div className="modal-header">
                <h5 className="modal-title d-flex align-items-center">
                  <IconLock size={20} className="me-2" />
                  Управление IPSec паролями
                </h5>
                <button type="button" className="btn-close" onClick={() => setIpsecPasswordsListModalOpen(false)}></button>
              </div>
              <div className="modal-body">
                <div className="d-flex justify-content-between align-items-center mb-3">
                  <div>
                    <h6 className="mb-0">Сохраненные IPSec пароли</h6>
                    <div className="text-muted small">Пароли хранятся в зашифрованном виде в S3</div>
                  </div>
                  <button
                    className="btn btn-primary btn-sm"
                    onClick={() => {
                      setIpsecPasswordModalMode('add');
                      setEditingIpsecPassword({ name: '', password: '', description: '' });
                      setIpsecPasswordModalOpen(true);
                    }}
                  >
                    <IconPlus size={16} className="me-1" />
                    Добавить пароль
                  </button>
                </div>
                {ipsecPasswords.length === 0 ? (
                  <div className="empty">
                    <div className="empty-img">
                      <IconLock size={48} />
                    </div>
                    <p className="empty-title">IPSec пароли не найдены</p>
                    <p className="empty-subtitle text-muted">
                      Создайте первый IPSec пароль для использования в шаблонах интерфейсов
                    </p>
                    <div className="empty-action">
                      <button
                        className="btn btn-primary"
                        onClick={() => {
                          setIpsecPasswordModalMode('add');
                          setEditingIpsecPassword({ name: '', password: '', description: '' });
                          setIpsecPasswordModalOpen(true);
                        }}
                      >
                        <IconPlus size={16} className="me-2" />
                        Добавить пароль
                      </button>
                    </div>
                  </div>
                ) : (
                  <div className="table-responsive">
                    <table className="table table-vcenter card-table">
                      <thead>
                        <tr>
                          <th>Название</th>
                          <th>Описание</th>
                          <th className="text-end">Действия</th>
                        </tr>
                      </thead>
                      <tbody>
                        {ipsecPasswords.map(pwd => (
                          <tr key={pwd.id}>
                            <td><strong>{pwd.name}</strong></td>
                            <td className="text-muted">{pwd.description || '—'}</td>
                            <td className="text-end">
                              <div className="btn-list gap-1">
                                <button
                                  className="btn btn-ghost-primary btn-icon btn-sm"
                                  onClick={() => {
                                    handleEditIpsecPassword(pwd.id);
                                    setIpsecPasswordsListModalOpen(false);
                                  }}
                                  title="Редактировать"
                                >
                                  <IconEdit size={16} />
                                </button>
                                <button
                                  className="btn btn-ghost-danger btn-icon btn-sm"
                                  onClick={() => {
                                    if (confirm(`Удалить пароль "${pwd.name}"?`)) {
                                      handleDeleteIpsecPassword(pwd.id);
                                    }
                                  }}
                                  title="Удалить"
                                >
                                  <IconTrash size={16} />
                                </button>
                              </div>
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                )}
              </div>
              <div className="modal-footer">
                <button type="button" className="btn btn-secondary" onClick={() => setIpsecPasswordsListModalOpen(false)}>
                  Закрыть
                </button>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* Pool Modal */}
      <FormModal
        show={poolModalOpen}
        onClose={() => { setPoolModalOpen(false); setEditingPool(null); }}
        onSubmit={() => editingPool && handleSavePool(editingPool)}
        title={poolModalMode === 'add' ? 'Добавить IP пул' : 'Редактировать IP пул'}
        submitLabel={poolModalMode === 'add' ? 'Добавить' : 'Сохранить'}
        submitIcon={poolModalMode === 'add' ? IconPlus : IconEdit}
      >
        {editingPool && (
          <div className="row g-3">
            <div className="col-md-6">
              <FormField
                label="Название"
                name="name"
                value={editingPool.name}
                onChange={(val) => setEditingPool({ ...editingPool, name: val })}
                placeholder="GRE Tunnels"
                required
              />
            </div>
            <div className="col-md-6">
              <FormField
                label="CIDR"
                name="cidr"
                value={editingPool.cidr}
                onChange={(val) => setEditingPool({ ...editingPool, cidr: val })}
                placeholder="10.10.0.0/24"
                required
              />
            </div>
            <div className="col-12">
              <FormField
                label="Описание"
                name="description"
                value={editingPool.description}
                onChange={(val) => setEditingPool({ ...editingPool, description: val })}
                placeholder="Пул для GRE туннелей между серверами"
              />
            </div>
          </div>
        )}
      </FormModal>

      {/* Delete Confirmation Modal */}
      <ConfirmModal
        show={deleteModalOpen}
        onClose={() => { setDeleteModalOpen(false); setItemToDelete(null); }}
        onConfirm={executeDelete}
        title="Подтверждение удаления"
        message={
          itemToDelete ? (
            <>
              <p>Вы уверены, что хотите удалить <strong>{itemToDelete.ip || itemToDelete.name || itemToDelete.cidr || 'этот элемент'}</strong>?</p>
              <p className="text-muted mb-0">Это действие нельзя отменить.</p>
            </>
          ) : null
        }
        confirmLabel="Удалить"
        variant="danger"
        icon={IconTrash}
      />

      {/* MikroTik Code Modal */}
      {mikrotikCodeModalOpen && (
        <div className="modal show d-block" style={{ backgroundColor: 'rgba(0,0,0,0.5)' }}>
          <div className="modal-dialog modal-xl">
            <div className="modal-content">
              <div className="modal-header">
                <h5 className="modal-title">
                  Предварительный просмотр конфигурации MikroTik
                </h5>
                <button type="button" className="btn-close" onClick={() => setMikrotikCodeModalOpen(false)}></button>
              </div>
              <div className="modal-body">
                <div className="alert alert-info mb-3">
                  Конфигурация MikroTik RouterOS для рекурсивных маршрутов и IP адресов интерфейсов
                </div>
                
                {Object.keys(groupedMikrotikCode).length > 0 ? (
                  <div className="d-flex flex-column gap-4">
                    {Object.entries(groupedMikrotikCode)
                      .sort(([a], [b]) => a.localeCompare(b))
                      .map(([serverName, serverData]) => {
                        const server = serverData.server;
                        const isUnassigned = serverName === '__unassigned__';
                        
                        return (
                          <div key={serverName} className="border rounded p-3">
                            {/* Заголовок сервера */}
                            <div className="d-flex align-items-center mb-3 pb-2 border-bottom">
                              <div className="d-flex align-items-center flex-fill">
                                {isUnassigned ? (
                                  <>
                                    <span className="avatar avatar-sm bg-secondary-lt me-2">
                                      <IconServer size={16} className="text-muted" />
                                    </span>
                                    <span className="text-muted">Без привязки к серверу</span>
                                  </>
                                ) : (
                                  <>
                                    <span className="avatar avatar-sm bg-primary-lt me-2">
                                      <IconServer size={16} className="text-primary" />
                                    </span>
                                    <div>
                                      <div className="fw-bold">{serverName}</div>
                                      {server && (
                                        <div className="text-muted small">
                                          {server.provider && <span>{server.provider}</span>}
                                          {server.provider && server.country && <span className="mx-1">•</span>}
                                          {server.country && (
                                            <span>{countryToFlag(server.country)} {server.country}</span>
                                          )}
                                          {server.ip && server.ip !== serverName && (
                                            <>
                                              {(server.provider || server.country) && <span className="mx-1">•</span>}
                                              <span>{server.ip}</span>
                                            </>
                                          )}
                                        </div>
                                      )}
                                    </div>
                                  </>
                                )}
                              </div>
                            </div>
                            
                            {/* Блоки кода для этого сервера */}
                            <div className="d-flex flex-column gap-3">
                              {serverData.blocks.map((block, blockIndex) => {
                                const blockTitle = block.type === 'recursive-routes' 
                                  ? 'Рекурсивные маршруты'
                                  : block.type === 'interface-addresses'
                                  ? 'IP адреса интерфейсов'
                                  : 'Конфигурация';
                                
                                return (
                                  <div key={blockIndex} className="border rounded overflow-hidden">
                                    {/* Заголовок блока */}
                                    <div className="bg-secondary-lt px-3 py-2 d-flex align-items-center justify-content-between">
                                      <div className="d-flex align-items-center">
                                        <IconCode size={18} className="text-secondary me-2" />
                                        <span className="fw-medium">{blockTitle}</span>
                                      </div>
                                      <button
                                        className="btn btn-sm btn-outline-secondary"
                                        onClick={() => handleCopyBlock(block.code)}
                                        title="Копировать этот блок"
                                      >
                                        <IconCopy size={16} className="me-1" />
                                        Копировать
                                      </button>
                                    </div>
                                    
                                    {/* Код блока */}
                                    <div className="bg-dark text-white p-3">
                                      <pre className="mb-0" style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word', fontSize: '0.875rem' }}>
                                        <code className="text-white">{block.code}</code>
                                      </pre>
                                    </div>
                                  </div>
                                );
                              })}
                            </div>
                          </div>
                        );
                      })}
                  </div>
                ) : (
                  <div className="alert alert-warning mb-0">
                    Нет данных для генерации конфигурации
                  </div>
                )}
                
                <div className="mt-3 text-muted small">
                  <p className="mb-1"><strong>Инструкция по применению:</strong></p>
                  <ol className="mb-0">
                    <li>Скопируйте конфигурацию в буфер обмена</li>
                    <li>Подключитесь к MikroTik через SSH или Winbox</li>
                    <li>Вставьте конфигурацию в терминал</li>
                    <li>Проверьте применение командой: <code>/ip route print</code> или <code>/ip address print</code></li>
                  </ol>
                </div>
              </div>
              <div className="modal-footer">
                <button type="button" className="btn btn-secondary" onClick={() => setMikrotikCodeModalOpen(false)}>
                  Закрыть
                </button>
                <button 
                  type="button"
                  className="btn btn-primary"
                  onClick={handleCopyAllMikrotikCode}
                  disabled={!Array.isArray(generatedMikrotikCode) || generatedMikrotikCode.length === 0}
                >
                  <IconCopy className="me-2" />
                  Копировать всё
                </button>
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

export default NetworkConfigManager;
