import { useState, useEffect, useRef, useCallback } from 'react';
import api from './lib/api.js';
import CommunityAutocompleteInput from './components/CommunityAutocompleteInput.jsx';
import CommunityBadge from './components/CommunityBadge.jsx';
import ConfirmModal from './components/ConfirmModal.jsx';
import { 
  IconPlus, 
  IconSearch, 
  IconEdit, 
  IconTrash, 
  IconCheck, 
  IconX, 
  IconDatabase,
  IconRefresh,
  IconUpload,
  IconDownload,
  IconDeviceFloppy,
  IconHash,
  IconClock,
  IconFileText,
  IconFilter,
  IconWorld,
  IconTrendingUp,
  IconUsers,
  IconArrowUp,
  IconArrowDown,
  IconCopy
} from '@/lib/icons';
import TableSkeleton, { TableEmpty } from './components/TableSkeleton.jsx';
import PageHeader from './components/PageHeader.jsx';
import EmptyState from './components/EmptyState.jsx';
import { IconAlertTriangle } from '@/lib/icons';
import { PageHeaderActions } from '@/components/shared/navigation';
import { ConfirmDialog, ErrorAlert } from '@/components/shared/feedback';
import WsUpdateModal from './components/WsUpdateModal.jsx';
import ConfirmDiffModal from './components/ConfirmDiffModal.jsx';
import HistoryModal from './components/HistoryModal.jsx';
import { notifyMutationSuccess } from './components/NotifyProvider.jsx';
import ImportModal from './components/ImportModal.jsx';
import QuickAddBar from './components/QuickAddBar.jsx';
import AccordionCard from './components/AccordionCard.jsx';
import SavedFilters from './components/SavedFilters.jsx';
import BulkActionsBar from './components/BulkActionsBar.jsx';
import FormField from './components/FormField.jsx';
import Tooltip from './components/Tooltip.jsx';
import Pagination from './components/Pagination.jsx';
import AddItemModal from './components/AddItemModal.jsx';
import LastSaved from './components/LastSaved.jsx';
import FormModal from './components/FormModal.jsx';
import { useToast } from './components/ToastContainer.jsx';
import {
  listCommunities,
  fetchDomainsData,
  saveDomainsData,
} from './lib/evobgpData.js';

function DomainsNewManager() {
  const toast = useToast();
  const [items, setItems] = useState([]);
  const [originalItems, setOriginalItems] = useState([]);
  const [, setEtag] = useState('');
  const [lastModified, setLastModified] = useState('');
  const [, setContentLength] = useState(null);
  const [newItem, setNewItem] = useState({ domain: '', community: '' });
  const [, setNewInvalid] = useState({ domain: false, community: false });
  const [error, setError] = useState('');
  const [success, setSuccess] = useState('');
  const [searchTerm, setSearchTerm] = useState('');
  const _searchTimer = useRef(null);
  const didInit = useRef(false);
  const [editingValue, setEditingValue] = useState('');
  const [editModalOpen, setEditModalOpen] = useState(false);
  const [itemBeingEdited, setItemBeingEdited] = useState(null);
  const [loading, setLoading] = useState(false);
  const [showDeleteModal, setShowDeleteModal] = useState(false);
  const [itemToDelete, setItemToDelete] = useState(null);
  const [addModalOpen, setAddModalOpen] = useState(false);
  const [currentPage, setCurrentPage] = useState(1);
  const [totalItems, setTotalItems] = useState(0);
  const [sortField, setSortField] = useState('domain');
  const [sortOrder, setSortOrder] = useState('asc');
  const [filterCommunity, setFilterCommunity] = useState('');
  const pageSize = 10;

  // Bulk operations
  const [selectedDomains, setSelectedDomains] = useState(new Set());

  // Справочник community для подсказок
  const [communities, setCommunities] = useState([]);
  useEffect(() => {
    const controller = new AbortController();
    const signal = controller.signal;
    (async () => {
      try {
        const list = await listCommunities();
        setCommunities(list);
      } catch (err) {
        if (err?.name === 'CanceledError' || err?.name === 'AbortError' || err?.code === 'ERR_CANCELED') return;
      }
    })();
    (async () => {
      try {
        const r = await api.get('/ws/url', { signal });
        setWsUrl(String(r.data?.url || ''));
      } catch (err) {
        if (err?.name === 'CanceledError' || err?.name === 'AbortError' || err?.code === 'ERR_CANCELED') return;
      }
    })();
    return () => controller.abort();
  }, []);

  const renderCommunityBadge = (value) => (<CommunityBadge value={value} communities={communities} />);

  const isValidDomain = (value) => {
    const v = String(value).trim().toLowerCase();
    // Простой валидатор FQDN: sub.domain.tld
    return /^([a-z0-9-]+\.)+[a-z]{2,}$/i.test(v);
  };

  // Допускаем как числовые, так и строковые (AS:NNN) community
  const isValidCommunity = (value) => /^(\d+|\d+:\d+)$/.test(String(value).trim());

  const [wsOpen, setWsOpen] = useState(false);
  const [wsUrl, setWsUrl] = useState('');

  const fetchItems = useCallback(async (_abortSignal) => {
    setLoading(true);
    try {
      const payload = await fetchDomainsData();
      const total = payload.length;
      setItems(payload);
      setOriginalItems(payload);
      setTotalItems(Number.isFinite(total) ? total : 0);
      setEtag('');
      setLastModified(new Date().toISOString());
      setContentLength(null);
      setError('');
    } catch (error) {
      if (error?.name === 'CanceledError' || error?.name === 'AbortError' || error?.code === 'ERR_CANCELED') return;
      console.error('Error fetching domains-new:', error);
      setError('Не удалось загрузить домены. Проверьте, запущен ли бэкенд.');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    if (!didInit.current) {
      didInit.current = true;
      const controller = new AbortController();
      fetchItems(controller.signal);
      return () => controller.abort();
    }
  }, [fetchItems]);

  const handleAddItem = (item) => {
    // Если item передан (из модалки), используем его, иначе из state (старый способ)
    const domain = item?.domain || newItem.domain;
    const community = item?.community || newItem.community;
    
    const domainOk = isValidDomain(domain);
    const communityOk = isValidCommunity(community);
    
    if (!domainOk || !communityOk) {
      setError('Заполните корректный домен (example.com) и числовой community.');
      return;
    }
    
    setError('');
    const newDomain = { domain: domain.trim().toLowerCase(), community: String(community).trim() };
    setItems([...items, newDomain]);
    if (!item) setNewItem({ domain: '', community: '' }); // Сброс только если не из модалки
    setNewInvalid({ domain: false, community: false });
  };

  const handleEdit = (item) => {
    setItemBeingEdited(item);
    setEditingValue(item.community);
    setEditModalOpen(true);
  };

  const handleSaveEdit = () => {
    if (!itemBeingEdited) return;
    if (!isValidCommunity(editingValue)) {
      setError('Community должен быть числом.');
      return;
    }
    const updatedItems = items.map(i =>
      i.domain === itemBeingEdited.domain ? { ...i, community: String(editingValue).trim() } : i
    );
    setItems(updatedItems);
    setEditModalOpen(false);
    setItemBeingEdited(null);
  };

  const handleCancelEdit = () => {
    setEditModalOpen(false);
    setItemBeingEdited(null);
  };

  const handleDeleteItem = (domainNameToDelete) => {
    setItems(items.filter(i => i.domain !== domainNameToDelete));
    setSelectedDomains(prev => {
      const next = new Set(prev);
      next.delete(domainNameToDelete);
      return next;
    });
  };

  const copyToClipboard = (text) => {
    navigator.clipboard.writeText(text).then(() => {
      toast.success('Скопировано в буфер обмена');
    }).catch(() => {
      toast.error('Не удалось скопировать');
    });
  };

  const confirmDelete = (item) => {
    setItemToDelete(item);
    setShowDeleteModal(true);
  };

  const executeDelete = () => {
    if (itemToDelete) {
      handleDeleteItem(itemToDelete.domain);
      setShowDeleteModal(false);
      setItemToDelete(null);
    }
  };

  const deduplicate = (arr) => {
    const seen = new Set();
    const out = [];
    for (const i of arr) {
      const key = String(i.domain).trim().toLowerCase();
      if (!key) continue;
      if (seen.has(key)) continue;
      seen.add(key);
      out.push({ domain: key, community: String(i.community || '').trim() });
    }
    return out;
  };

  const computeDiff = (before, after) => {
    const mapBefore = new Map(before.map(i => [i.domain, i]));
    const mapAfter = new Map(after.map(i => [i.domain, i]));
    const added = [];
    const removed = [];
    const changed = [];
    for (const [k, v] of mapAfter) {
      if (!mapBefore.has(k)) { added.push(v); continue; }
      const prev = mapBefore.get(k);
      if (String(prev.community) !== String(v.community)) changed.push({ from: prev, to: v });
    }
    for (const [k, v] of mapBefore) {
      if (!mapAfter.has(k)) removed.push(v);
    }
    return { added, removed, changed };
  };

  const [showDiff, setShowDiff] = useState(false);
  const [diff, setDiff] = useState({ added: [], removed: [], changed: [] });
  const [confirmSaveOpen, setConfirmSaveOpen] = useState(false);
  const [historyOpen, setHistoryOpen] = useState(false);
  const [clearCommunitiesOpen, setClearCommunitiesOpen] = useState(false);

  const handlePreviewDiff = () => {
    const valid = items.filter(i => i != null && isValidDomain(i.domain) && isValidCommunity(i.community))
      .map(i => ({ domain: i.domain.trim().toLowerCase(), community: String(i.community).trim() }));
    const unique = deduplicate(valid);
    setDiff(computeDiff(originalItems, unique));
    setShowDiff(true);
  };

  const performSave = useCallback(async () => {
    setConfirmSaveOpen(false);
    setLoading(true);
    try {
      const valid = items.filter(i => isValidDomain(i.domain) && isValidCommunity(i.community))
        .map(i => ({ domain: i.domain.trim().toLowerCase(), community: String(i.community).trim() }));
      const unique = deduplicate(valid);

      await saveDomainsData(unique, originalItems);
      setEtag('');
      // После сохранения перезагрузим текущую страницу для консистентности
      await fetchItems();
      setSuccess('Изменения успешно сохранены!');
      setTimeout(() => setSuccess(''), 3000);
      notifyMutationSuccess('Изменения сохранены');
    } catch (error) {
      console.error('Error saving changes:', error);
      setError('Не удалось сохранить изменения.');
    } finally {
      setLoading(false);
    }
  }, [items, originalItems, fetchItems]);

  const handleSaveChanges = useCallback(async () => {
    const valid = items.filter(i => i != null && isValidDomain(i.domain) && isValidCommunity(i.community))
      .map(i => ({ domain: i.domain.trim().toLowerCase(), community: String(i.community).trim() }));
    const unique = deduplicate(valid);
    const diffData = computeDiff(originalItems, unique);
    setDiff(diffData);
    const totalChanges = (diffData.added?.length || 0) + (diffData.removed?.length || 0) + (diffData.changed?.length || 0);
    if (totalChanges > 10) {
      setConfirmSaveOpen(true);
    } else {
      performSave();
    }
  }, [items, originalItems, performSave]);

  // Drag&Drop импорт
  const _onDropImport = async (e) => {
    e.preventDefault();
    const file = e.dataTransfer?.files?.[0];
    if (!file) return;
    const text = await file.text();
    const lines = text.split(/\r?\n/).map(l => l.trim()).filter(Boolean);
    const parsed = lines.map(l => {
      const [d, c] = l.split(/\s+/);
      return { domain: (d || '').toLowerCase(), community: (c || '').trim() };
    }).filter(i => i != null && isValidDomain(i.domain) && isValidCommunity(i.community));
    setItems(prev => {
      const merged = [...prev, ...parsed];
      const map = new Map();
      for (const it of merged) {
        const key = String(it.domain).trim().toLowerCase();
        if (!map.has(key)) map.set(key, { domain: key, community: String(it.community).trim() });
      }
      return Array.from(map.values());
    });
  };

  const handleImport = () => {
    setImportOpen(true);
  };

  const handleExport = async () => {
    try {
      const all = filtered;
      const header = ['domain', 'community'];
      const csv = [header, ...all.filter(i => i != null).map(i => [i.domain || '', i.community || ''])]
        .map(r => r.map(x => `"${(x ?? '').toString().replace(/"/g, '""')}"`).join(','))
        .join('\n');
      const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `domains_${new Date().toISOString().split('T')[0]}.csv`;
      a.click();
      URL.revokeObjectURL(url);
    } catch (e) {
      window.notify?.error('Экспорт доменов не удался', String(e?.message || e));
    }
  };

  const clearInvalid = () => {
    setItems(prev => prev.filter(i => i != null && (i.domain || i.community))
      .filter(i => isValidDomain(i.domain) && isValidCommunity(i.community))
    );
  };

  // ===== Импорт через модалку =====
  const [importOpen, setImportOpen] = useState(false);
  const parseLine = (line) => {
    const [d, c] = String(line).split(/\s+/);
    return { domain: (d || '').toLowerCase(), community: (c || '').trim() };
  };
  const validateItem = (obj) => isValidDomain(obj.domain) && isValidCommunity(obj.community);
  const applyImportedItems = (list) => {
    setItems(prev => {
      const merged = [...prev, ...list];
      const map = new Map();
      for (const it of merged) {
        const key = String(it.domain).trim().toLowerCase();
        if (!map.has(key)) map.set(key, { domain: key, community: String(it.community).trim() });
      }
      return Array.from(map.values());
    });
    setImportOpen(false);
  };

  // Сортировка
  const sortedItems = [...items].sort((a, b) => {
    let valA = a[sortField] || '';
    let valB = b[sortField] || '';
    if (typeof valA === 'string') valA = valA.toLowerCase();
    if (typeof valB === 'string') valB = valB.toLowerCase();
    if (valA < valB) return sortOrder === 'asc' ? -1 : 1;
    if (valA > valB) return sortOrder === 'asc' ? 1 : -1;
    return 0;
  });

  // Локальная фильтрация и пагинация
  const filtered = sortedItems.filter(i => {
    if (!i) return false;
    const byCommunity = !filterCommunity || i.community === filterCommunity;
    const term = String(searchTerm || '').toLowerCase();
    const bySearch = !term || String(i.domain || '').toLowerCase().includes(term);
    return byCommunity && bySearch;
  });
  const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
  const paginatedItems = filtered.slice((currentPage - 1) * pageSize, (currentPage) * pageSize);

  // Для фильтра - список всех уникальных community
  const allCommunities = Array.from(new Set(items.filter(i => i != null).map(i => i.community).filter(c => c != null)));

  // Сортировка по клику
  const handleSort = (field) => {
    if (sortField === field) {
      setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc');
    } else {
      setSortField(field);
      setSortOrder('asc');
    }
  };

  // Глобальные хоткеи: Ctrl+S — сохранить изменения
  useEffect(() => {
    const onKey = (e) => {
      if ((e.ctrlKey || e.metaKey) && (e.key === 's' || e.key === 'S')) {
        e.preventDefault();
        if (!loading) handleSaveChanges();
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [loading, handleSaveChanges]);

  const handleEditKeyDown = (e) => {
    if (e.key === 'Enter') {
      e.preventDefault();
      handleSaveEdit();
    }
    if (e.key === 'Escape') {
      e.preventDefault();
      handleCancelEdit();
    }
  };

  // Bulk operations handlers
  const handleSelectAll = () => {
    setSelectedDomains(new Set(paginatedItems.map(i => i.domain)));
  };

  const handleDeselectAll = () => {
    setSelectedDomains(new Set());
  };

  const handleToggleSelect = (domain) => {
    const newSet = new Set(selectedDomains);
    if (newSet.has(domain)) {
      newSet.delete(domain);
    } else {
      newSet.add(domain);
    }
    setSelectedDomains(newSet);
  };

  const handleBulkDelete = () => {
    if (selectedDomains.size === 0) return;
    const count = selectedDomains.size;
    const newItems = items.filter(i => !selectedDomains.has(i.domain));
    setItems(newItems);
    setSelectedDomains(new Set());
    toast.success(`Удалено ${count} доменов`);
  };

  const handleBulkExport = () => {
    if (selectedDomains.size === 0) return;
    const selectedItems = items.filter(i => i != null && selectedDomains.has(i.domain));
    const text = selectedItems.map(i => `${i.domain || ''} ${i.community || ''}`).join('\n');
    const blob = new Blob([text], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `domains-selected-${selectedDomains.size}.txt`;
    a.click();
    URL.revokeObjectURL(url);
    toast.success(`Экспортировано ${selectedDomains.size} доменов`);
  };

  return (
    <>
      {error && (
        <ErrorAlert message={error} onClose={() => setError('')} />
      )}
      
      {success && (
        <div className="alert alert-success alert-dismissible" role="alert">
          <div className="d-flex">
            <div>
              <IconCheck className="icon alert-icon" />
            </div>
            <div>
              {success}
            </div>
          </div>
          <button type="button" className="btn-close" onClick={() => setSuccess('')}></button>
        </div>
      )}

      <PageHeader
        title="Домены"
        icon={<IconWorld size={24} />}
        meta={<LastSaved timestamp={lastModified} variant="compact" />}
        actions={(
          <PageHeaderActions
            loading={loading}
            onPreview={handlePreviewDiff}
            disablePreview={loading || items.length === 0}
            onRefresh={fetchItems}
            disableRefresh={loading}
            onImport={handleImport}
            onExport={handleExport}
            disableExport={items.length === 0}
            onClear={clearInvalid}
            disableClear={items.length === 0}
            onClearCommunities={() => { if (!filterCommunity) { setError('Выберите community в фильтре для очистки'); return; } setClearCommunitiesOpen(true); }}
            disableClearCommunities={items.length === 0 || !filterCommunity}
            onSave={handleSaveChanges}
            disableSave={loading}
            onHistory={() => setHistoryOpen(true)}
            lastModified={lastModified}
            onOnlineUpdate={() => setWsOpen(true)}
            onBackgroundUpdate={async () => {
              try {
                const res = await fetch('/api/update-bgp/background', { method: 'POST' });
                const data = await res.json().catch(() => ({}));
                if (!res.ok || data.ok === false) {
                  throw new Error(data?.message || `HTTP ${res.status}`);
                }
                notifyMutationSuccess('Фоновое обновление запущено', data);
              } catch (e) {
                window.notify?.error('Не удалось запустить фоновое обновление', String(e));
              }
            }}
          />
        )}
      />

      <AddItemModal
        open={addModalOpen}
        onClose={() => setAddModalOpen(false)}
        onSubmit={handleAddItem}
        type="domain"
        communities={communities}
        loading={loading}
      />

      <div className="row">
        <div className="col-12">
          {/* Bulk Actions Bar */}
          <BulkActionsBar
            selectedCount={selectedDomains.size}
            totalCount={paginatedItems.length}
            onSelectAll={handleSelectAll}
            onDeselectAll={handleDeselectAll}
            onDelete={handleBulkDelete}
            onExport={handleBulkExport}
          />

          <div className="card card-flat animate-in" style={{animationDelay: '0.3s'}}>
            <div className="card-header">
              <div className="row align-items-center w-100 g-2">
                <div className="col">
                  <div className="d-flex align-items-center justify-content-between flex-wrap gap-2">
                    <div className="d-flex align-items-center gap-2">
                      <IconWorld className="icon text-muted" size={18} />
                      <span className="text-muted text-uppercase small">Список</span>
                      <span className="badge bg-blue-lt text-blue">{filtered.length}</span>
                    </div>
                    <div className="d-none d-md-block text-muted small">
                      Всего записей: {filtered.length}
                    </div>
                  </div>
                </div>
                <div className="col-12 mt-2"></div>
                <div className="col">
                  <div className="d-flex gap-2 flex-wrap">
                    {/* Сохранённые фильтры */}
                    <SavedFilters
                      pageKey="domains"
                      currentFilters={{ searchTerm, filterCommunity, sortField, sortOrder }}
                      onApplyFilter={(filters) => {
                        if (filters.searchTerm !== undefined) setSearchTerm(filters.searchTerm);
                        if (filters.filterCommunity !== undefined) setFilterCommunity(filters.filterCommunity);
                        if (filters.sortField !== undefined) setSortField(filters.sortField);
                        if (filters.sortOrder !== undefined) setSortOrder(filters.sortOrder);
                        setCurrentPage(1);
                      }}
                    />
                    
                    {/* Фильтр по community */}
                    <div className="input-icon">
                      <span className="input-icon-addon">
                        <IconFilter size={18} />
                      </span>
                      <select
                        className="form-select"
                        style={{ minWidth: '200px' }}
                        value={filterCommunity}
                        onChange={e => { setFilterCommunity(e.target.value); setCurrentPage(1); }}
                        title={(() => {
                          const meta = communities.find(c => c.value === filterCommunity);
                          if (!meta) return 'Все community';
                          const name = meta.name ? meta.name + ' — ' : '';
                          const desc = meta.description || '';
                          const tags = meta.tags && meta.tags.length ? ' (' + meta.tags.join(', ') + ')' : '';
                          return name + desc + tags;
                        })()}
                      >
                        <option value="">Все community</option>
                        {allCommunities.map(community => {
                          const meta = communities.find(c => c.value === community);
                          const label = meta && meta.name ? `${community} — ${meta.name}` : community;
                          const title = meta ? `${meta.name ? meta.name + ' — ' : ''}${meta.description || ''}${meta.tags && meta.tags.length ? ' (' + meta.tags.join(', ') + ')' : ''}` : community;
                          return (
                            <option key={community} value={community} title={title}>{label}</option>
                          );
                        })}
                      </select>
                    </div>
                    
                    {/* Поиск */}
                    <div className="input-icon flex-grow-1" style={{ minWidth: '200px', position: 'relative' }}>
                      <span className="input-icon-addon">
                        <IconSearch size={18} />
                      </span>
                      <input
                        type="text"
                        className="form-control"
                        placeholder="Поиск домена..."
                        value={searchTerm}
                        onChange={e => { setSearchTerm(e.target.value); setCurrentPage(1); }}
                        aria-label="Поиск домена"
                        style={{ paddingRight: searchTerm ? '2.5rem' : undefined }}
                      />
                      {searchTerm && (
                        <button
                          type="button"
                          className="btn btn-ghost-secondary btn-icon btn-sm"
                          style={{ 
                            position: 'absolute', 
                            right: '0.25rem', 
                            top: '50%', 
                            transform: 'translateY(-50%)',
                            zIndex: 2
                          }}
                          onClick={() => { setSearchTerm(''); setCurrentPage(1); }}
                          aria-label="Очистить поиск"
                        >
                          <IconX size={16} />
                        </button>
                      )}
                    </div>
                  </div>
                </div>
                <div className="col-auto">
                  <button
                    className="btn btn-primary"
                    onClick={() => setAddModalOpen(true)}
                    title="Добавить новый домен"
                  >
                    <IconPlus className="me-1" size={18} />
                    Добавить
                  </button>
                </div>
              </div>
            </div>
            <div className="card-body p-0">
              {/* Таблица с лёгкой карточной подложкой (плоский стиль) */}
              {loading ? (
                <TableSkeleton rows={10} cols={4} hasCheckbox={true} flat />
              ) : paginatedItems.length === 0 ? (
                <TableEmpty cols={3} flat>
                  <EmptyState
                    title="Нет доменов"
                    description="Импортируйте или добавьте записи, чтобы начать."
                    action={<button className="btn btn-primary" onClick={handleImport}>Импорт</button>}
                    secondaryAction={<button className="btn btn-outline-primary" onClick={() => {
                      const header = ['domain','community'];
                      const lines = [header, ['example.com','65000:100']].map(r => r.map(x => `"${(x ?? '').toString().replace(/"/g, '""')}"`).join(',')).join('\n');
                      const blob = new Blob([lines], { type: 'text/csv;charset=utf-8;' });
                      const url = URL.createObjectURL(blob);
                      const a = document.createElement('a'); a.href = url; a.download = 'domains_sample.csv'; a.click(); URL.revokeObjectURL(url);
                    }}>Шаблон CSV</button>}
                  />
                </TableEmpty>
              ) : (
                <div className="table-responsive">
                  <table className="table table-flat table-vcenter table-nowrap mb-0">
                    <thead>
                      <tr>
                        <th style={{ width: '40px' }}>
                          <input
                            type="checkbox"
                            className="form-check-input"
                            checked={selectedDomains.size === paginatedItems.length && paginatedItems.length > 0}
                            onChange={(e) => e.target.checked ? handleSelectAll() : handleDeselectAll()}
                          />
                        </th>
                        <th className="cursor-pointer user-select-none" onClick={() => handleSort('domain')}>
                          <div className="d-flex align-items-center">
                            <IconWorld size={16} className="me-1 text-muted" />
                            Домен
                            {sortField === 'domain' && (
                              <span className="ms-1">
                                {sortOrder === 'asc' ? <IconArrowUp size={14} /> : <IconArrowDown size={14} />}
                              </span>
                            )}
                          </div>
                        </th>
                        <th className="cursor-pointer user-select-none" onClick={() => handleSort('community')}>
                          <div className="d-flex align-items-center">
                            <IconHash size={16} className="me-1 text-muted" />
                            Community
                            {sortField === 'community' && (
                              <span className="ms-1">
                                {sortOrder === 'asc' ? <IconArrowUp size={14} /> : <IconArrowDown size={14} />}
                              </span>
                            )}
                          </div>
                        </th>
                        <th className="text-end">Действия</th>
                      </tr>
                    </thead>
                    <tbody>
                      {paginatedItems.map((item, idx) => (
                        <tr 
                          key={item.domain} 
                          className={selectedDomains.has(item.domain) ? 'table-selected' : ''}
                          style={{
                            animation: `fadeIn 0.3s ease ${idx * 0.02}s both`
                          }}
                        >
                          <td>
                            <input
                              type="checkbox"
                              className="form-check-input"
                              checked={selectedDomains.has(item.domain)}
                              onChange={() => handleToggleSelect(item.domain)}
                              aria-label={`Выбрать ${item.domain}`}
                              onClick={(e) => e.stopPropagation()}
                            />
                          </td>
                          <td>
                            <div className="d-flex align-items-center">
                              <IconWorld size={16} className="me-2 text-muted" />
                              <span className="font-monospace">{item.domain}</span>
                              <Tooltip content="Копировать домен" position="top">
                                <button
                                  className="btn btn-ghost-secondary btn-icon btn-sm ms-2"
                                  onClick={() => copyToClipboard(item.domain)}
                                  aria-label="Копировать"
                                  title="Копировать домен"
                                >
                                  <IconCopy size={14} />
                                </button>
                              </Tooltip>
                            </div>
                          </td>
                          <td>
                            <div className="d-flex align-items-center">
                              {renderCommunityBadge(item.community)}
                            </div>
                          </td>
                          <td className="text-end">
                            <div className="btn-group btn-group-sm" role="group" aria-label={`Действия с доменом ${item.domain}`}>
                              <Tooltip content="Редактировать" position="top">
                                <button 
                                  className="btn btn-icon btn-outline-primary" 
                                  aria-label="Редактировать" 
                                  onClick={() => handleEdit(item)}
                                  title="Редактировать"
                                >
                                  <IconEdit size={16} />
                                </button>
                              </Tooltip>
                              <Tooltip content="Удалить" position="top">
                                <button 
                                  className="btn btn-icon btn-outline-danger" 
                                  aria-label="Удалить" 
                                  onClick={() => confirmDelete(item)}
                                  title="Удалить"
                                >
                                  <IconTrash size={16} />
                                </button>
                              </Tooltip>
                            </div>
                          </td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              )}
            </div>
            <div className="card-footer border-top-0">
              <Pagination
                currentPage={currentPage}
                totalPages={totalPages}
                totalItems={totalItems || filtered.length}
                pageSize={pageSize}
                onPageChange={setCurrentPage}
              />
            </div>
          </div>
        </div>
      </div>

      <ConfirmModal
        show={showDeleteModal}
        onClose={() => setShowDeleteModal(false)}
        onConfirm={executeDelete}
        title="Удалить домен?"
        message={
          itemToDelete ? (
            <>
              <p>Вы уверены, что хотите удалить <strong>"{itemToDelete.domain}"</strong>?</p>
              <p className="text-muted mb-0">Это действие необратимо.</p>
            </>
          ) : null
        }
        confirmLabel="Удалить"
        variant="danger"
        icon={IconTrash}
      />
      {/* Confirm Save Modal */}
      <ConfirmDiffModal
        show={confirmSaveOpen}
        diff={diff}
        onConfirm={performSave}
        onClose={() => setConfirmSaveOpen(false)}
      />
      <ImportModal
        show={importOpen}
        title={'Импорт доменов'}
        description={'Формат: DOMAIN ПРОБЕЛ COMMUNITY'}
        parseLine={parseLine}
        validateItem={validateItem}
        onConfirm={applyImportedItems}
        onClose={() => setImportOpen(false)}
        sampleHeader={['domain','community']}
        placeholder={'example.com 65000:100'}
      />
      <HistoryModal
        resource="domains-new"
        show={historyOpen}
        onClose={() => setHistoryOpen(false)}
        onRolledBack={() => fetchItems()}
      />
      <WsUpdateModal
        show={wsOpen}
        url={wsUrl}
        onClose={() => setWsOpen(false)}
      />
      {/* Модальное окно редактирования community */}
      <FormModal
        show={editModalOpen && !!itemBeingEdited}
        onClose={handleCancelEdit}
        onSubmit={handleSaveEdit}
        title="Редактировать community"
        submitLabel="Сохранить"
        submitIcon={IconCheck}
        size="md"
        centered
        disabled={!isValidCommunity(editingValue)}
      >
        {itemBeingEdited && (
          <>
            <p className="text-muted mb-2">
              Домен: <span className="font-monospace">{itemBeingEdited.domain}</span>
            </p>
            <div className="mb-3">
              <label className="form-label">Community</label>
              <CommunityAutocompleteInput
                value={editingValue}
                onChange={setEditingValue}
                communities={communities}
                onKeyDown={handleEditKeyDown}
                className={`form-control${isValidCommunity(editingValue) ? '' : ' is-invalid'}`}
                useShortValue={true}
              />
              {!isValidCommunity(editingValue) && (
                <div className="invalid-feedback d-block">
                  Введите корректное значение community (число или N:N).
                </div>
              )}
            </div>
          </>
        )}
      </FormModal>
      <ConfirmModal
        show={clearCommunitiesOpen}
        onClose={() => setClearCommunitiesOpen(false)}
        onConfirm={() => { 
          setItems(prev => prev.filter(i => i != null && i.community !== filterCommunity)); 
          setClearCommunitiesOpen(false); 
        }}
        title="Удалить записи community?"
        message={
          <>
            <p>Будут удалены все домены с community <strong>"{filterCommunity}"</strong>.</p>
            <p className="text-warning mb-0">
              <IconAlertTriangle size={16} className="me-1" />
              Действие НЕ сохраняет изменения автоматически.
            </p>
          </>
        }
        confirmLabel="Удалить"
        variant="warning"
      />
      {/* Diff Modal */}
      {showDiff && (
        <div className="modal modal-blur fade show" style={{display: 'block'}} tabIndex="-1">
          <div className="modal-dialog modal-lg modal-dialog-centered" role="document">
            <div className="modal-content">
              <button type="button" className="btn-close" onClick={() => setShowDiff(false)}></button>
              <div className="modal-header"><h3 className="modal-title">Изменения</h3></div>
              <div className="modal-body">
                <div className="row g-2 g-md-3">
                  <div className="col-6 col-md-4"><div className="card"><div className="card-body py-2"><strong>Добавлено</strong><div className="text-muted">{diff.added.length}</div></div></div></div>
                  <div className="col-6 col-md-4"><div className="card"><div className="card-body py-2"><strong>Удалено</strong><div className="text-muted">{diff.removed.length}</div></div></div></div>
                  <div className="col-6 col-md-4"><div className="card"><div className="card-body py-2"><strong>Изменено</strong><div className="text-muted">{diff.changed.length}</div></div></div></div>
                </div>
              </div>
              <div className="modal-footer">
                <button className="btn" onClick={() => setShowDiff(false)}>Закрыть</button>
              </div>
            </div>
          </div>
        </div>
      )}
      {/* datalist больше не нужен, т.к. используем кастомный автокомплит */}
    </>
  );
}

export default DomainsNewManager; 