/**
 * NexusPrinter — Web USB / Web Serial bridge for thermal printers.
 *
 * Connects to 58mm or 80mm ESC/POS printers via WebUSB or Web Serial APIs
 * and sends raw byte commands generated by the backend.
 */
window.NexusPrinter = (function () {
    'use strict';

    let _device = null;       // WebUSB device
    let _endpoint = null;     // USB bulk-out endpoint number
    let _serialPort = null;   // Web Serial port
    let _writer = null;       // Serial writable stream writer
    let _type = null;         // 'usb' | 'serial' | null

    // ── Connection ─────────────────────────────────

    async function connect() {
        // Try WebUSB first
        if ('usb' in navigator) {
            try {
                _device = await navigator.usb.requestDevice({ filters: [] });
                await _device.open();

                // Select first configuration if needed
                if (_device.configuration === null) {
                    await _device.selectConfiguration(1);
                }

                // Claim first interface and find bulk-out endpoint
                const iface = _device.configuration.interfaces[0];
                await _device.claimInterface(iface.interfaceNumber);

                const alt = iface.alternates[0];
                const ep = alt.endpoints.find(e => e.direction === 'out' && e.type === 'bulk');
                if (ep) {
                    _endpoint = ep.endpointNumber;
                    _type = 'usb';
                    _save();
                    return { ok: true, type: 'usb', name: _device.productName || 'USB Printer' };
                }
            } catch (e) {
                // User cancelled or no USB device available
                _device = null;
            }
        }

        // Fall back to Web Serial
        if ('serial' in navigator) {
            try {
                _serialPort = await navigator.serial.requestPort();
                await _serialPort.open({ baudRate: 9600 });
                _writer = _serialPort.writable.getWriter();
                _type = 'serial';
                _save();
                return { ok: true, type: 'serial', name: 'Serial Printer' };
            } catch (e) {
                _serialPort = null;
                _writer = null;
            }
        }

        return { ok: false, error: 'No printer connected. Use a browser that supports WebUSB or Web Serial (Chrome/Edge).' };
    }

    async function disconnect() {
        try {
            if (_type === 'usb' && _device) {
                await _device.close();
            }
            if (_type === 'serial') {
                if (_writer) { _writer.releaseLock(); _writer = null; }
                if (_serialPort) { await _serialPort.close(); _serialPort = null; }
            }
        } catch (e) { /* ignore */ }
        _device = null;
        _endpoint = null;
        _type = null;
        localStorage.removeItem('nexus_printer');
    }

    function isConnected() {
        return _type !== null;
    }

    // ── Printing ───────────────────────────────────

    async function sendRaw(bytes) {
        if (!_type) return false;

        try {
            if (_type === 'usb' && _device && _endpoint !== null) {
                // Send in chunks of 512 bytes (common USB max packet size)
                const chunk = 512;
                for (let i = 0; i < bytes.length; i += chunk) {
                    await _device.transferOut(_endpoint, bytes.slice(i, i + chunk));
                }
                return true;
            }
            if (_type === 'serial' && _writer) {
                await _writer.write(bytes);
                return true;
            }
        } catch (e) {
            console.error('[NexusPrinter] send error:', e);
            // Connection likely lost
            await disconnect();
        }
        return false;
    }

    /**
     * Print a sale ticket by fetching ESC/POS bytes from the backend.
     * @param {number} saleId
     * @param {number} [width=80] — 58 or 80 mm
     * @returns {Promise<boolean>}
     */
    async function printSale(saleId, width) {
        width = width || 80;
        const token = localStorage.getItem('pos_token');
        const resp = await fetch('/pos/api/sales/' + saleId + '/print', {
            method: 'POST',
            headers: {
                'Authorization': 'Bearer ' + token,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ printer_type: 'escpos_raw', width: width })
        });
        if (!resp.ok) {
            console.error('[NexusPrinter] backend error', resp.status);
            return false;
        }
        const buf = await resp.arrayBuffer();
        return sendRaw(new Uint8Array(buf));
    }

    /**
     * Print a workshop service order ticket.
     * @param {number} soId
     * @param {number} [width=80] — 58 or 80 mm
     * @returns {Promise<boolean>}
     */
    async function printServiceOrder(soId, width) {
        width = width || 80;
        const token = localStorage.getItem('pos_token');
        const resp = await fetch('/pos/api/service-orders/' + soId + '/print', {
            method: 'POST',
            headers: {
                'Authorization': 'Bearer ' + token,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ printer_type: 'escpos_raw', width: width })
        });
        if (!resp.ok) {
            console.error('[NexusPrinter] backend error', resp.status);
            return false;
        }
        const buf = await resp.arrayBuffer();
        return sendRaw(new Uint8Array(buf));
    }

    // ── Persistence helpers ────────────────────────

    function _save() {
        try { localStorage.setItem('nexus_printer', _type || ''); } catch (e) {}
    }

    // ── Public API ─────────────────────────────────

    return {
        connect: connect,
        disconnect: disconnect,
        isConnected: isConnected,
        sendRaw: sendRaw,
        printSale: printSale,
        printServiceOrder: printServiceOrder
    };
})();
