{{define "title"}}QFS Партномера{{end}}

{{define "content"}}
<div class="space-y-4">
    <h1 class="text-2xl font-bold text-gray-900">Партномера</h1>

    <!-- Summary cards -->
    <div id="summary-cards" class="grid grid-cols-2 md:grid-cols-3 gap-4 hidden">
        <div class="bg-white rounded-lg shadow p-4">
            <div class="text-xs text-gray-500 mb-1">Активный лист</div>
            <div id="card-version" class="font-mono font-semibold text-gray-800 text-sm truncate">—</div>
            <div id="card-date" class="text-xs text-gray-400 mt-0.5">—</div>
        </div>
        <div class="bg-white rounded-lg shadow p-4">
            <div class="text-xs text-gray-500 mb-1">Уникальных LOT</div>
            <div id="card-lots" class="text-2xl font-bold text-blue-600">—</div>
        </div>
        <div class="bg-white rounded-lg shadow p-4">
            <div class="text-xs text-gray-500 mb-1">Всего PN</div>
            <div id="card-pn-total" class="text-2xl font-bold text-gray-800">—</div>
        </div>
    </div>

    <div id="summary-empty" class="hidden bg-yellow-50 border border-yellow-200 rounded-lg p-4 text-sm text-yellow-800">
        Нет активного листа сопоставлений. Книги загружаются автоматически вместе с прайслистами.
    </div>

    <!-- All books list (collapsed by default) -->
    <div class="bg-white rounded-lg shadow overflow-hidden">
        <!-- Header row — always visible -->
        <div class="px-4 py-3">
            <button onclick="toggleBooksSection()" class="flex items-center gap-2 text-sm font-semibold text-gray-800 hover:text-gray-600 select-none">
                <svg id="books-chevron" class="w-4 h-4 text-gray-400 transition-transform duration-150" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M9 5l7 7-7 7"/></svg>
                Снимки сопоставлений (Partnumber Books)
            </button>
        </div>
        <!-- Collapsible body -->
        <div id="books-section-body" class="hidden border-t">
            <div id="books-list-loading" class="p-6 text-center text-gray-400 text-sm">Загрузка...</div>
            <table id="books-table" class="w-full text-sm hidden">
                <thead class="bg-gray-50 text-gray-600">
                    <tr>
                        <th class="px-4 py-2 text-left">Версия</th>
                        <th class="px-4 py-2 text-left">Дата</th>
                        <th class="px-4 py-2 text-right">Позиций</th>
                        <th class="px-4 py-2 text-center">Статус</th>
                    </tr>
                </thead>
                <tbody id="books-table-body"></tbody>
            </table>
            <div id="books-empty" class="hidden p-6 text-center text-gray-400 text-sm">
                Нет загруженных снимков.
            </div>
            <!-- Pagination -->
            <div id="books-pagination" class="hidden px-4 py-3 border-t flex items-center justify-between text-sm text-gray-600">
                <span id="books-page-info"></span>
                <div class="flex gap-2">
                    <button id="books-prev" onclick="changeBooksPage(-1)" class="px-3 py-1 rounded border hover:bg-gray-50 disabled:opacity-40 disabled:cursor-not-allowed">← Назад</button>
                    <button id="books-next" onclick="changeBooksPage(1)"  class="px-3 py-1 rounded border hover:bg-gray-50 disabled:opacity-40 disabled:cursor-not-allowed">Вперёд →</button>
                </div>
            </div>
        </div>
    </div>

    <!-- Active book items with search -->
    <div id="active-book-section" class="hidden bg-white rounded-lg shadow overflow-hidden">
        <div class="px-4 py-3 border-b flex items-center justify-between gap-3">
            <span class="font-semibold text-gray-800 whitespace-nowrap">Сопоставления активного листа</span>
            <input type="text" id="pn-search" placeholder="Поиск по PN, LOT или описанию..."
                   class="flex-1 max-w-xs px-3 py-1.5 border rounded text-sm focus:ring-2 focus:ring-blue-400 focus:outline-none"
                   oninput="onItemsSearchInput(this.value)">
            <span id="pn-count" class="text-xs text-gray-400 whitespace-nowrap"></span>
        </div>
        <div class="overflow-x-auto">
            <table class="w-full text-sm">
                <thead class="bg-gray-50 text-gray-600 sticky top-0">
                    <tr>
                        <th class="px-4 py-2 text-left">Partnumber</th>
                        <th class="px-4 py-2 text-left">LOT</th>
                        <th class="px-4 py-2 text-left">Описание</th>
                    </tr>
                </thead>
                <tbody id="active-items-body"></tbody>
            </table>
        </div>
        <div id="items-pagination" class="hidden px-4 py-3 border-t flex items-center justify-between text-sm text-gray-600">
            <span id="items-page-info"></span>
            <div class="flex gap-2">
                <button id="items-prev" onclick="changeItemsPage(-1)" class="px-3 py-1 rounded border hover:bg-gray-50 disabled:opacity-40 disabled:cursor-not-allowed">← Назад</button>
                <button id="items-next" onclick="changeItemsPage(1)" class="px-3 py-1 rounded border hover:bg-gray-50 disabled:opacity-40 disabled:cursor-not-allowed">Вперёд →</button>
            </div>
        </div>
    </div>
</div>


<script>
let allBooks = [];
let booksPage = 1;
const BOOKS_PER_PAGE = 10;
const ITEMS_PER_PAGE = 100;
let activeBookServerID = null;
let activeItems = [];
let itemsPage = 1;
let itemsTotal = 0;
let itemsSearch = '';
let _itemsSearchTimer = null;

function toggleBooksSection() {
    const body = document.getElementById('books-section-body');
    const chevron = document.getElementById('books-chevron');
    const collapsed = body.classList.toggle('hidden');
    chevron.style.transform = collapsed ? '' : 'rotate(90deg)';
}

async function loadBooks() {
    let resp, data;
    try {
        resp = await fetch('/api/partnumber-books');
        data = await resp.json();
    } catch (e) {
        document.getElementById('books-list-loading').classList.add('hidden');
        document.getElementById('books-empty').classList.remove('hidden');
        return;
    }

    allBooks = data.items || [];
    document.getElementById('books-list-loading').classList.add('hidden');

    if (!allBooks.length) {
        document.getElementById('books-empty').classList.remove('hidden');
        document.getElementById('summary-empty').classList.remove('hidden');
        return;
    }

    booksPage = 1;
    renderBooksPage();

    const active = allBooks.find(b => b.is_active) || allBooks[0];
    await loadActiveBookItems(active);
}

function renderBooksPage() {
    const total = allBooks.length;
    const totalPages = Math.ceil(total / BOOKS_PER_PAGE);
    const start = (booksPage - 1) * BOOKS_PER_PAGE;
    const pageBooks = allBooks.slice(start, start + BOOKS_PER_PAGE);

    const tbody = document.getElementById('books-table-body');
    tbody.innerHTML = '';
    pageBooks.forEach(b => {
        const tr = document.createElement('tr');
        tr.className = 'border-b hover:bg-gray-50';
        tr.innerHTML = `
            <td class="px-4 py-2 font-mono text-xs">${b.version}</td>
            <td class="px-4 py-2 text-gray-500 text-xs">${b.created_at}</td>
            <td class="px-4 py-2 text-right text-xs">${b.item_count}</td>
            <td class="px-4 py-2 text-center">
                ${b.is_active
                    ? '<span class="px-2 py-0.5 bg-green-100 text-green-700 rounded text-xs">Активный</span>'
                    : '<span class="px-2 py-0.5 bg-gray-100 text-gray-500 rounded text-xs">Архив</span>'}
            </td>
        `;
        tbody.appendChild(tr);
    });
    document.getElementById('books-table').classList.remove('hidden');

    // Pagination controls
    if (total > BOOKS_PER_PAGE) {
        document.getElementById('books-pagination').classList.remove('hidden');
        document.getElementById('books-page-info').textContent =
            `Снимки ${start + 1}–${Math.min(start + BOOKS_PER_PAGE, total)} из ${total}`;
        document.getElementById('books-prev').disabled = booksPage === 1;
        document.getElementById('books-next').disabled = booksPage === totalPages;
    } else {
        document.getElementById('books-pagination').classList.add('hidden');
    }
}

function changeBooksPage(delta) {
    const totalPages = Math.ceil(allBooks.length / BOOKS_PER_PAGE);
    booksPage = Math.max(1, Math.min(totalPages, booksPage + delta));
    renderBooksPage();
}

async function loadActiveBookItems(book) {
    activeBookServerID = book.server_id;
    return loadActiveBookItemsPage(1, itemsSearch, book);
}

async function loadActiveBookItemsPage(page = 1, search = '', book = null) {
    const targetBook = book || allBooks.find(b => b.server_id === activeBookServerID);
    if (!targetBook) return;

    let resp, data;
    try {
        const params = new URLSearchParams({
            page: String(page),
            per_page: String(ITEMS_PER_PAGE),
        });
        if (search.trim()) {
            params.set('search', search.trim());
        }
        resp = await fetch(`/api/partnumber-books/${targetBook.server_id}?` + params.toString());
        data = await resp.json();
    } catch (e) {
        return;
    }
    if (!resp.ok) return;

    activeItems = data.items || [];
    itemsPage = data.page || page;
    itemsTotal = Number(data.total_count || 0);
    itemsSearch = data.search || search || '';

    document.getElementById('card-version').textContent = targetBook.version;
    document.getElementById('card-date').textContent = targetBook.created_at;
    document.getElementById('card-lots').textContent = Number(data.lot_count || 0);
    document.getElementById('card-pn-total').textContent = Number(data.book_total || 0);
    document.getElementById('summary-cards').classList.remove('hidden');
    document.getElementById('active-book-section').classList.remove('hidden');
    document.getElementById('pn-search').value = itemsSearch;

    renderItems(activeItems);
    renderItemsPagination();
}

function renderItems(items) {
    const tbody = document.getElementById('active-items-body');
    tbody.innerHTML = '';
    items.forEach(item => {
        const tr = document.createElement('tr');
        tr.className = 'border-b hover:bg-gray-50';
        const lots = Array.isArray(item.lots_json) ? item.lots_json : [];
        const lotsText = lots.map(l => `${l.lot_name} x${l.qty}`).join(', ');
        tr.innerHTML = `
            <td class="px-4 py-1.5 font-mono text-xs">${item.partnumber}</td>
            <td class="px-4 py-1.5 text-xs font-medium text-blue-700">${lotsText}</td>
            <td class="px-4 py-1.5 text-xs text-gray-500">${item.description || ''}</td>
        `;
        tbody.appendChild(tr);
    });
    const totalLabel = itemsSearch ? `${items.length} из ${itemsTotal} по фильтру` : `${items.length} из ${itemsTotal}`;
    document.getElementById('pn-count').textContent = totalLabel;
}

function renderItemsPagination() {
    const totalPages = Math.max(1, Math.ceil(itemsTotal / ITEMS_PER_PAGE));
    const start = itemsTotal === 0 ? 0 : ((itemsPage - 1) * ITEMS_PER_PAGE) + 1;
    const end = Math.min(itemsPage * ITEMS_PER_PAGE, itemsTotal);
    const box = document.getElementById('items-pagination');
    if (itemsTotal > ITEMS_PER_PAGE) {
        box.classList.remove('hidden');
        document.getElementById('items-page-info').textContent = `Сопоставления ${start}–${end} из ${itemsTotal}`;
        document.getElementById('items-prev').disabled = itemsPage === 1;
        document.getElementById('items-next').disabled = itemsPage >= totalPages;
    } else {
        box.classList.add('hidden');
    }
}

function changeItemsPage(delta) {
    const totalPages = Math.max(1, Math.ceil(itemsTotal / ITEMS_PER_PAGE));
    const nextPage = Math.max(1, Math.min(totalPages, itemsPage + delta));
    if (nextPage === itemsPage) return;
    loadActiveBookItemsPage(nextPage, itemsSearch);
}

function onItemsSearchInput(value) {
    clearTimeout(_itemsSearchTimer);
    _itemsSearchTimer = setTimeout(() => {
        itemsSearch = value.trim();
        loadActiveBookItemsPage(1, itemsSearch);
    }, 250);
}

async function syncPartnumberBooks() {
    let resp, data;
    try {
        resp = await fetch('/api/sync/partnumber-books', {method: 'POST'});
        data = await resp.json();
    } catch (e) {
        showToast('Ошибка синхронизации', 'error');
        return;
    }
    if (data.success) {
        showToast(`Синхронизировано: ${data.synced} листов`, 'success');
        loadBooks();
    } else if (data.blocked) {
        showToast(`Синк заблокирован: ${data.reason_text}`, 'error');
    } else {
        showToast('Ошибка: ' + (data.error || 'неизвестная ошибка'), 'error');
    }
}

document.addEventListener('DOMContentLoaded', loadBooks);
</script>
{{end}}

{{template "base" .}}
