/**
 * Serial Numbers Tracker - Frontend Logic
 */

const API_BASE = (window.API_CONFIG && window.API_CONFIG.BASE_URL) || '/api/v1';
let allSerials = [];
let serializedProducts = [];
let branches = [];
let currentFilters = {};
let viewingSerialId = null;

function authHeaders() {
    if (window.authBootstrap && typeof window.authBootstrap.authHeader === 'function') {
        return window.authBootstrap.authHeader();
    }
    if (window.auth && typeof window.auth.authHeader === 'function') {
        return window.auth.authHeader();
    }
    const token = localStorage.getItem('token');
    return token ? { Authorization: `Bearer ${token}` } : {};
}

function formatApiError(data, fallback) {
    if (!data) return fallback || 'Request failed';
    const detail = data.detail;
    if (typeof detail === 'string') return detail;
    if (Array.isArray(detail)) {
        return detail.map((d) => d.msg || d.message || JSON.stringify(d)).join('; ');
    }
    if (data.message) return data.message;
    return fallback || 'Request failed';
}

function unwrapList(data) {
    if (Array.isArray(data)) return data;
    if (data && Array.isArray(data.data)) return data.data;
    if (data && Array.isArray(data.items)) return data.items;
    return [];
}

async function apiGet(url) {
    const response = await fetch(url, { headers: authHeaders() });
    const data = await response.json().catch(() => ({}));
    if (!response.ok) throw new Error(formatApiError(data, response.statusText));
    return data;
}

async function apiSend(url, method, body) {
    const response = await fetch(url, {
        method,
        headers: { ...authHeaders(), 'Content-Type': 'application/json' },
        body: JSON.stringify(body),
    });
    const data = await response.json().catch(() => ({}));
    if (!response.ok) throw new Error(formatApiError(data, response.statusText));
    return data;
}

document.addEventListener('DOMContentLoaded', () => {
    loadBranches();
    loadSerializedProducts();
    loadSerialNumbers();
    setupEventListeners();
});

function setupEventListeners() {
    document.getElementById('searchBtn').addEventListener('click', performSearch);
    document.getElementById('serialSearch').addEventListener('keypress', (e) => {
        if (e.key === 'Enter') performSearch();
    });

    document.getElementById('productFilter').addEventListener('change', applyFilters);
    document.getElementById('statusFilter').addEventListener('change', applyFilters);
    document.getElementById('branchFilter').addEventListener('change', applyFilters);
    document.getElementById('batchFilter').addEventListener('input', debounce(applyFilters, 500));
    document.getElementById('locationFilter').addEventListener('input', debounce(applyFilters, 500));
    document.getElementById('clearFiltersBtn').addEventListener('click', clearFilters);

    document.querySelectorAll('.filter-chip').forEach((chip) => {
        chip.addEventListener('click', function () {
            document.querySelectorAll('.filter-chip').forEach((c) => c.classList.remove('active'));
            this.classList.add('active');
            quickFilter(this.dataset.filter);
        });
    });

    document.getElementById('saveSerialBtn').addEventListener('click', saveNewSerial);
    document.getElementById('bulkSerials').addEventListener('input', updateBulkCount);
    document.getElementById('bulkImportBtn').addEventListener('click', bulkImportSerials);

    document.getElementById('serialsTableBody').addEventListener('click', (e) => {
        const btn = e.target.closest('[data-action="view-serial"]');
        if (btn && btn.dataset.serialId) {
            viewSerial(btn.dataset.serialId);
        }
    });

    document.getElementById('updateSerialBtn').addEventListener('click', updateSerial);
}

async function loadBranches() {
    try {
        const data = await apiGet(`${API_BASE}/branches?limit=200`);
        branches = unwrapList(data);

        const selects = ['addBranchSelect', 'bulkBranchSelect', 'branchFilter'];
        selects.forEach((selectId) => {
            const select = document.getElementById(selectId);
            const defaultOption = selectId === 'branchFilter' ? 'All Branches' : 'Not assigned';
            select.innerHTML = `<option value="">${defaultOption}</option>`;
            branches.forEach((b) => {
                const option = document.createElement('option');
                option.value = b.id;
                option.textContent = b.name;
                select.appendChild(option);
            });
        });
    } catch (error) {
        console.error('Error loading branches:', error);
    }
}

function debounce(func, wait) {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
}

function clearFilters() {
    document.getElementById('productFilter').value = '';
    document.getElementById('statusFilter').value = '';
    document.getElementById('branchFilter').value = '';
    document.getElementById('batchFilter').value = '';
    document.getElementById('locationFilter').value = '';
    document.getElementById('serialSearch').value = '';
    document.querySelectorAll('.filter-chip').forEach((c) => c.classList.remove('active'));
    currentFilters = {};
    loadSerialNumbers();
}

async function loadSerializedProducts() {
    try {
        const data = await apiGet(`${API_BASE}/inventory/products?limit=500&active_only=true`);
        const products = unwrapList(data);
        serializedProducts = products.filter((p) => p.is_serialized);

        ['addProductSelect', 'bulkProductSelect'].forEach((selectId) => {
            const select = document.getElementById(selectId);
            select.innerHTML = '<option value="">Select a serialized product...</option>';
            serializedProducts.forEach((p) => {
                const option = document.createElement('option');
                option.value = p.id;
                option.textContent = `${p.name} (${p.sku || 'no SKU'})`;
                select.appendChild(option);
            });
        });

        const filterSelect = document.getElementById('productFilter');
        filterSelect.innerHTML = '<option value="">All Products</option>';
        serializedProducts.forEach((p) => {
            const option = document.createElement('option');
            option.value = p.id;
            option.textContent = p.name;
            filterSelect.appendChild(option);
        });
    } catch (error) {
        console.error('Error loading products:', error);
        showAlert(error.message || 'Failed to load products', 'danger');
    }
}

async function loadSerialNumbers(filters = {}) {
    try {
        const params = new URLSearchParams({ limit: '500' });
        Object.entries(filters).forEach(([key, value]) => {
            if (value !== undefined && value !== null && value !== '') {
                params.set(key, value);
            }
        });

        const data = await apiGet(`${API_BASE}/serial-numbers?${params}`);
        allSerials = unwrapList(data);
        renderSerialNumbers(allSerials);
        updateStatistics(allSerials);
    } catch (error) {
        console.error('Error loading serial numbers:', error);
        showAlert(error.message || 'Failed to load serial numbers', 'danger');
    }
}

function renderSerialNumbers(serials) {
    const tbody = document.getElementById('serialsTableBody');
    document.getElementById('resultsCount').textContent = `${serials.length} results`;

    if (serials.length === 0) {
        tbody.innerHTML = `
            <tr>
                <td colspan="10" class="text-center text-muted py-4">
                    <i class="bi bi-inbox fs-1 d-block mb-2"></i>
                    No serial numbers found. Try adjusting your filters or add a new serial number.
                </td>
            </tr>
        `;
        return;
    }

    tbody.innerHTML = serials.map((serial) => `
        <tr>
            <td>
                <strong>${escapeHtml(serial.serial)}</strong>
                <br><small class="text-muted">${escapeHtml((serial.id || '').substring(0, 8))}…</small>
            </td>
            <td>
                <div>${escapeHtml(serial.product_name || 'N/A')}</div>
                <small class="text-muted">${escapeHtml(serial.product_sku || '')}</small>
            </td>
            <td>
                <span class="badge status-badge status-${escapeHtml(serial.status || '')}">
                    ${formatStatus(serial.status)}
                </span>
            </td>
            <td>${escapeHtml(serial.batch_number || '-')}</td>
            <td>${escapeHtml(serial.branch_name || '-')}</td>
            <td>${escapeHtml(serial.location || '-')}</td>
            <td>${escapeHtml(serial.customer_name || '-')}</td>
            <td>${formatWarranty(serial.warranty_expires_at)}</td>
            <td>
                <small>
                    ${serial.purchase_date ? `Purchased: ${formatDate(serial.purchase_date)}<br>` : ''}
                    ${serial.sold_at ? `Sold: ${formatDate(serial.sold_at)}<br>` : ''}
                    ${serial.returned_at ? `Returned: ${formatDate(serial.returned_at)}` : ''}
                </small>
            </td>
            <td>
                <div class="btn-group btn-group-sm">
                    <button type="button" class="btn btn-outline-primary" data-action="view-serial"
                        data-serial-id="${escapeHtml(serial.id)}" title="View / Edit">
                        <i class="bi bi-eye"></i>
                    </button>
                    <a href="/static/traceability.html?q=${encodeURIComponent(serial.serial)}&lookup_type=serial&v=20260602"
                       target="_blank" class="btn btn-outline-info" title="Trace History">
                        <i class="bi bi-diagram-3"></i>
                    </a>
                </div>
            </td>
        </tr>
    `).join('');
}

function updateStatistics(serials) {
    const stats = {
        available: serials.filter((s) => s.status === 'available').length,
        sold: serials.filter((s) => s.status === 'sold').length,
        warrantyExpiring: serials.filter((s) => isWarrantyExpiring(s.warranty_expires_at)).length,
        total: serials.length,
    };

    document.getElementById('availableCount').textContent = stats.available;
    document.getElementById('soldCount').textContent = stats.sold;
    document.getElementById('warrantyExpiringCount').textContent = stats.warrantyExpiring;
    document.getElementById('totalCount').textContent = stats.total;
}

async function performSearch() {
    const searchTerm = document.getElementById('serialSearch').value.trim();
    if (!searchTerm) {
        loadSerialNumbers(currentFilters);
        return;
    }

    try {
        const lookup = await fetch(
            `${API_BASE}/serial-numbers/lookup/${encodeURIComponent(searchTerm)}`,
            { headers: authHeaders() }
        );
        if (lookup.ok) {
            const serial = await lookup.json();
            renderSerialNumbers([serial]);
            updateStatistics([serial]);
            return;
        }

        const data = await apiGet(
            `${API_BASE}/serial-numbers?search=${encodeURIComponent(searchTerm)}&limit=500`
        );
        const matches = unwrapList(data);
        if (matches.length === 0) {
            showAlert('No serial numbers match your search', 'warning');
        }
        renderSerialNumbers(matches);
        updateStatistics(matches);
    } catch (error) {
        console.error('Search error:', error);
        showAlert(error.message || 'Search failed', 'danger');
    }
}

function applyFilters() {
    const filters = {};

    const productId = document.getElementById('productFilter').value;
    if (productId) filters.product_id = productId;

    const status = document.getElementById('statusFilter').value;
    if (status) filters.status = status;

    const branchId = document.getElementById('branchFilter').value;
    if (branchId) filters.branch_id = branchId;

    const batchNumber = document.getElementById('batchFilter').value.trim();
    if (batchNumber) filters.batch_number = batchNumber;

    const location = document.getElementById('locationFilter').value.trim();
    if (location) filters.location = location;

    currentFilters = filters;
    loadSerialNumbers(filters);
}

function quickFilter(type) {
    const filters = { ...currentFilters };

    switch (type) {
        case 'available':
            filters.status = 'available';
            document.getElementById('statusFilter').value = 'available';
            loadSerialNumbers(filters);
            break;
        case 'sold':
            filters.status = 'sold';
            document.getElementById('statusFilter').value = 'sold';
            loadSerialNumbers(filters);
            break;
        case 'returned':
            filters.status = 'returned';
            document.getElementById('statusFilter').value = 'returned';
            loadSerialNumbers(filters);
            break;
        case 'warranty-expiring': {
            const expiring = allSerials.filter((s) => isWarrantyExpiring(s.warranty_expires_at));
            renderSerialNumbers(expiring);
            updateStatistics(expiring);
            break;
        }
        default:
            break;
    }
}

async function saveNewSerial() {
    const productId = document.getElementById('addProductSelect').value;
    const serial = document.getElementById('addSerial').value.trim();
    const status = document.getElementById('addStatus').value;
    const batchNumber = document.getElementById('addBatch').value.trim();
    const branchId = document.getElementById('addBranchSelect').value;
    const location = document.getElementById('addLocation').value.trim();
    const notes = document.getElementById('addNotes').value.trim();

    if (!productId || !serial) {
        showAlert('Please fill in all required fields', 'warning');
        return;
    }

    const payload = {
        product_id: productId,
        serial,
        status,
        batch_number: batchNumber || null,
        branch_id: branchId || null,
        location: location || null,
        notes: notes || null,
    };

    try {
        await apiSend(`${API_BASE}/serial-numbers`, 'POST', payload);
        showAlert('Serial number created successfully', 'success');
        bootstrap.Modal.getInstance(document.getElementById('addSerialModal')).hide();
        document.getElementById('addSerialForm').reset();
        loadSerialNumbers(currentFilters);
    } catch (error) {
        console.error('Error creating serial:', error);
        showAlert(error.message, 'danger');
    }
}

function updateBulkCount() {
    const text = document.getElementById('bulkSerials').value;
    const lines = text.split('\n').filter((line) => line.trim()).length;
    document.getElementById('bulkCount').textContent = lines;
    document.getElementById('bulkCountBtn').textContent = lines;
}

async function bulkImportSerials() {
    const productId = document.getElementById('bulkProductSelect').value;
    const serialsText = document.getElementById('bulkSerials').value;
    const batchNumber = document.getElementById('bulkBatch').value.trim();
    const branchId = document.getElementById('bulkBranchSelect').value;
    const location = document.getElementById('bulkLocation').value.trim();
    const status = document.getElementById('bulkStatus').value;

    if (!productId || !serialsText.trim()) {
        showAlert('Please fill in all required fields', 'warning');
        return;
    }

    const serials = serialsText.split('\n').map((s) => s.trim()).filter((s) => s.length > 0);
    if (serials.length === 0) {
        showAlert('Please enter at least one serial number', 'warning');
        return;
    }

    const payload = {
        product_id: productId,
        serials,
        status,
        batch_number: batchNumber || null,
        branch_id: branchId || null,
        location: location || null,
        notes: `Bulk import on ${new Date().toLocaleDateString()}`,
    };

    try {
        const result = await apiSend(`${API_BASE}/serial-numbers`, 'POST', payload);
        const count = unwrapList(result).length || serials.length;
        showAlert(`Successfully imported ${count} serial number(s)`, 'success');
        bootstrap.Modal.getInstance(document.getElementById('bulkImportModal')).hide();
        document.getElementById('bulkSerials').value = '';
        document.getElementById('bulkBatch').value = '';
        document.getElementById('bulkBranchSelect').value = '';
        document.getElementById('bulkLocation').value = '';
        updateBulkCount();
        loadSerialNumbers(currentFilters);
    } catch (error) {
        console.error('Bulk import error:', error);
        showAlert(error.message, 'danger');
    }
}

async function viewSerial(serialId) {
    try {
        const serial = await apiGet(`${API_BASE}/serial-numbers/${serialId}`);
        viewingSerialId = serial.id;
        displaySerialDetails(serial);
        const modal = new bootstrap.Modal(document.getElementById('viewSerialModal'));
        modal.show();
    } catch (error) {
        console.error('Error loading serial:', error);
        showAlert(error.message || 'Failed to load serial details', 'danger');
    }
}

function displaySerialDetails(serial) {
    const body = document.getElementById('serialDetailsBody');
    const branchName = serial.branch_name || 'Not assigned';

    body.innerHTML = `
        <div class="row">
            <div class="col-md-6 mb-3">
                <label class="form-label fw-bold">Serial Number</label>
                <input type="text" class="form-control" value="${escapeHtml(serial.serial)}" readonly>
            </div>
            <div class="col-md-6 mb-3">
                <label class="form-label fw-bold">Status</label>
                <select class="form-select" id="editStatus">
                    <option value="available" ${serial.status === 'available' ? 'selected' : ''}>Available</option>
                    <option value="reserved" ${serial.status === 'reserved' ? 'selected' : ''}>Reserved</option>
                    <option value="sold" ${serial.status === 'sold' ? 'selected' : ''}>Sold</option>
                    <option value="returned" ${serial.status === 'returned' ? 'selected' : ''}>Returned</option>
                    <option value="void" ${serial.status === 'void' ? 'selected' : ''}>Void</option>
                    <option value="in_service" ${serial.status === 'in_service' ? 'selected' : ''}>In Service</option>
                </select>
            </div>
        </div>
        <div class="row">
            <div class="col-md-6 mb-3">
                <label class="form-label fw-bold">Product</label>
                <input type="text" class="form-control" value="${escapeHtml(serial.product_name || 'N/A')}" readonly>
            </div>
            <div class="col-md-6 mb-3">
                <label class="form-label fw-bold">Batch Number</label>
                <input type="text" class="form-control" id="editBatch" value="${escapeHtml(serial.batch_number || '')}">
            </div>
        </div>
        <div class="row">
            <div class="col-md-6 mb-3">
                <label class="form-label fw-bold">Branch</label>
                <input type="text" class="form-control" value="${escapeHtml(branchName)}" readonly>
                <small class="text-muted">Branch assignment cannot be changed after creation</small>
            </div>
            <div class="col-md-6 mb-3">
                <label class="form-label fw-bold">Location</label>
                <input type="text" class="form-control" id="editLocation" value="${escapeHtml(serial.location || '')}">
            </div>
        </div>
        <div class="row">
            <div class="col-md-6 mb-3">
                <label class="form-label fw-bold">Customer</label>
                <input type="text" class="form-control" value="${escapeHtml(serial.customer_name || 'N/A')}" readonly>
            </div>
            <div class="col-md-6 mb-3">
                <label class="form-label fw-bold">Warranty Expires</label>
                <input type="date" class="form-control" id="editWarrantyExpires"
                       value="${serial.warranty_expires_at ? String(serial.warranty_expires_at).slice(0, 10) : ''}">
            </div>
        </div>
        <div class="mb-3">
            <label class="form-label fw-bold">Notes</label>
            <textarea class="form-control" id="editNotes" rows="3">${escapeHtml(serial.notes || '')}</textarea>
        </div>
        <div class="row">
            <div class="col-md-4 mb-2">
                <small class="text-muted">Created:</small><br>
                <strong>${formatDateTime(serial.created_at)}</strong>
            </div>
            ${serial.sold_at ? `
            <div class="col-md-4 mb-2">
                <small class="text-muted">Sold:</small><br>
                <strong>${formatDate(serial.sold_at)}</strong>
            </div>
            ` : ''}
            ${serial.returned_at ? `
            <div class="col-md-4 mb-2">
                <small class="text-muted">Returned:</small><br>
                <strong>${formatDate(serial.returned_at)}</strong>
            </div>
            ` : ''}
        </div>
    `;

    const traceBtn = document.getElementById('traceSerialBtn');
    if (traceBtn) {
        traceBtn.href = `/static/traceability.html?q=${encodeURIComponent(serial.serial)}&lookup_type=serial&v=20260602`;
    }
}

async function updateSerial() {
    if (!viewingSerialId) return;

    const updates = {
        status: document.getElementById('editStatus').value,
        batch_number: document.getElementById('editBatch').value.trim() || null,
        location: document.getElementById('editLocation').value.trim() || null,
        warranty_expires_at: document.getElementById('editWarrantyExpires').value || null,
        notes: document.getElementById('editNotes').value.trim() || null,
    };

    try {
        await apiSend(`${API_BASE}/serial-numbers/${viewingSerialId}`, 'PATCH', updates);
        showAlert('Serial number updated successfully', 'success');
        bootstrap.Modal.getInstance(document.getElementById('viewSerialModal')).hide();
        loadSerialNumbers(currentFilters);
    } catch (error) {
        console.error('Update error:', error);
        showAlert(error.message, 'danger');
    }
}

function formatStatus(status) {
    if (!status) return 'Unknown';
    return status.replace('_', ' ').replace(/\b\w/g, (l) => l.toUpperCase());
}

function formatDate(dateStr) {
    if (!dateStr) return '-';
    return new Date(dateStr).toLocaleDateString();
}

function formatDateTime(dateStr) {
    if (!dateStr) return '-';
    return new Date(dateStr).toLocaleString();
}

function formatWarranty(expiryDate) {
    if (!expiryDate) return '<span class="text-muted">No warranty</span>';

    const expiry = new Date(expiryDate);
    const now = new Date();
    const daysLeft = Math.ceil((expiry - now) / (1000 * 60 * 60 * 24));

    if (daysLeft < 0) {
        return `<span class="warranty-expired">Expired ${formatDate(expiryDate)}</span>`;
    }
    if (daysLeft < 30) {
        return `<span class="warranty-expiring">Expires ${formatDate(expiryDate)} (${daysLeft}d)</span>`;
    }
    return `<span class="warranty-active">${formatDate(expiryDate)}</span>`;
}

function isWarrantyExpiring(expiryDate) {
    if (!expiryDate) return false;
    const expiry = new Date(expiryDate);
    const now = new Date();
    const daysLeft = Math.ceil((expiry - now) / (1000 * 60 * 60 * 24));
    return daysLeft > 0 && daysLeft < 30;
}

function escapeHtml(text) {
    if (text === null || text === undefined) return '';
    const div = document.createElement('div');
    div.textContent = String(text);
    return div.innerHTML;
}

function showAlert(message, type = 'info') {
    const alertDiv = document.createElement('div');
    alertDiv.className = `alert alert-${type} alert-dismissible fade show position-fixed top-0 start-50 translate-middle-x mt-3`;
    alertDiv.style.zIndex = '9999';
    alertDiv.innerHTML = `
        ${escapeHtml(message)}
        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
    `;
    document.body.appendChild(alertDiv);
    setTimeout(() => alertDiv.remove(), 5000);
}
