/**
 * Print System JavaScript Handler
 * WAMP Environment Compatible
 * Handles print operations, device management, and print modes
 */

class PrintSystem {
    constructor() {
        this.printSettings = null;
        this.devices = null;
        this.init();
    }
    
    async init() {
        await this.loadSettings();
        await this.loadDevices();
    }
    
    /**
     * Load print settings from server
     */
    async loadSettings() {
        try {
            const response = await fetch('ajax/get_print_settings.php');
            const data = await response.json();
            if (data.success) {
                this.printSettings = data.settings;
            }
        } catch (error) {
            console.error('Failed to load print settings:', error);
        }
    }
    
    /**
     * Load devices from server
     */
    async loadDevices() {
        try {
            // Get current terminal ID if available
            const terminalId = this.getTerminalId();
            const url = terminalId 
                ? `ajax/get_print_devices.php?terminal_id=${terminalId}`
                : 'ajax/get_print_devices.php';
            
            const response = await fetch(url);
            const data = await response.json();
            if (data.success) {
                this.devices = data.devices;
            }
        } catch (error) {
            console.error('Failed to load devices:', error);
        }
    }
    
    /**
     * Get current terminal ID
     */
    getTerminalId() {
        // Try to get from global function (defined in pos.php)
        if (typeof getCurrentTerminalId === 'function') {
            return getCurrentTerminalId();
        }
        // Try to get from sessionStorage
        return sessionStorage.getItem('terminal_id');
    }
    
    /**
     * Handle print operation
     */
    async handlePrint(printType, printData, options = {}) {
        try {
            // Get print mode for this type
            const printMode = await this.getPrintMode(printType);
            
            switch (printMode) {
                case 'ask':
                    return await this.showPrintDialog(printType, printData, options);
                case 'auto':
                    return await this.autoPrint(printType, printData, options);
                case 'no':
                    return { success: true, message: 'Printing skipped (No print mode)' };
                default:
                    return await this.showPrintDialog(printType, printData, options);
            }
        } catch (error) {
            console.error('Print operation failed:', error);
            return { success: false, message: error.message };
        }
    }
    
    /**
     * Get print mode for specific print type
     */
    async getPrintMode(printType) {
        try {
            const response = await fetch(`ajax/get_print_mode.php?print_type=${printType}`);
            const data = await response.json();
            return data.print_mode || 'ask';
        } catch (error) {
            console.error('Failed to get print mode:', error);
            return 'ask';
        }
    }
    
    /**
     * Show print dialog
     */
    async showPrintDialog(printType, printData, options = {}) {
        return new Promise((resolve) => {
            const devices = this.getDevicesForType(printType);
            
            if (devices.length === 0) {
                Swal.fire({
                    title: 'No Printers Available',
                    text: `No printers configured for ${printType} printing.`,
                    icon: 'warning',
                    confirmButtonText: 'OK'
                }).then(() => {
                    resolve({ success: false, message: 'No printers available' });
                });
                return;
            }
            
            // Create device selection options
            const deviceOptions = devices.map(device => 
                `<option value="${device.id}">${device.name} (${device.connection_type.toUpperCase()})</option>`
            ).join('');
            
            Swal.fire({
                title: `Print ${printType.toUpperCase()}`,
                html: `
                    <div class="mb-3">
                        <label class="form-label">Select Printer:</label>
                        <select id="printDeviceSelect" class="form-select">
                            ${deviceOptions}
                        </select>
                    </div>
                    <div class="form-check">
                        <input class="form-check-input" type="checkbox" id="printCopies" value="1">
                        <label class="form-check-label" for="printCopies">
                            Print Copy
                        </label>
                    </div>
                `,
                showCancelButton: true,
                confirmButtonText: 'Print',
                cancelButtonText: 'Cancel',
                preConfirm: () => {
                    const deviceId = document.getElementById('printDeviceSelect').value;
                    const printCopy = document.getElementById('printCopies').checked;
                    return { deviceId, printCopy };
                }
            }).then((result) => {
                if (result.isConfirmed) {
                    this.executePrint(printType, printData, result.value.deviceId, result.value.printCopy, options)
                        .then(resolve);
                } else {
                    resolve({ success: false, message: 'Print cancelled by user' });
                }
            });
        });
    }
    
    /**
     * Auto print to default device
     */
    async autoPrint(printType, printData, options = {}) {
        const defaultDevice = this.getDefaultDevice(printType);
        
        if (!defaultDevice) {
            // Check if we should skip dialog fallback (for direct printing)
            if (options.skipDialogFallback) {
                return { 
                    success: false, 
                    message: 'No default printer configured for ' + printType + ' printing' 
                };
            }
            // Fallback to print dialog
            return await this.showPrintDialog(printType, printData, options);
        }
        
        return await this.executePrint(printType, printData, defaultDevice.id, false, options);
    }
    
    /**
     * Execute print operation
     */
    async executePrint(printType, printData, deviceId, printCopy = false, options = {}) {
        try {
            const device = this.getDeviceById(deviceId);
            
            if (!device) {
                throw new Error('Device not found');
            }
            
            const configuredCopies = parseInt(device.copies, 10);
            const baseCopies = Number.isFinite(configuredCopies) && configuredCopies > 0 ? configuredCopies : 1;
            const extraCopies = printCopy ? 1 : 0;
            const totalCopies = baseCopies + extraCopies;

            let lastResult = null;

            for (let copyIndex = 0; copyIndex < totalCopies; copyIndex++) {
                // Execute print based on device type
                if (device.connection_type === 'lan') {
                    lastResult = await this.printToLAN(device, printData);
                } else {
                    lastResult = await this.printToUSB(device, printData);
                }

                if (!lastResult || !lastResult.success) {
                    const message = lastResult && lastResult.message ? lastResult.message : 'Unknown print error';
                    return {
                        success: false,
                        message: totalCopies > 1
                            ? `Printing stopped on copy ${copyIndex + 1} of ${totalCopies}: ${message}`
                            : message
                    };
                }
            }

            if (totalCopies > 1) {
                return {
                    success: true,
                    message: `Printed ${totalCopies} copies successfully`
                };
            }

            return lastResult || { success: true, message: 'Print completed successfully' };
            
        } catch (error) {
            console.error('Print execution failed:', error);
            return { success: false, message: error.message };
        }
    }
    
    /**
     * Print to LAN device (server-side)
     */
    async printToLAN(device, printData) {
        try {
            const response = await fetch('ajax/print_to_lan.php', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    device_id: device.id,
                    print_data: printData
                })
            });
            
            const result = await response.json();
            return result;
        } catch (error) {
            throw error;
        }
    }
    
    /**
     * Print to USB device (server-side direct printing)
     */
    async printToUSB(device, printData) {
        try {
            // Use server-side direct printing only
            const response = await fetch('ajax/print_to_usb.php', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    device_id: device.id,
                    print_data: printData
                })
            });
            
            // Check if response is OK
            if (!response.ok) {
                const text = await response.text();
                console.error('Print response error:', response.status, text);
                return { success: false, message: 'Server error: ' + response.status };
            }
            
            // Check content type before parsing JSON
            const contentType = response.headers.get('content-type');
            if (!contentType || !contentType.includes('application/json')) {
                const text = await response.text();
                console.error('Invalid response type. Expected JSON, got:', contentType, text.substring(0, 200));
                return { success: false, message: 'Server returned invalid response (expected JSON)' };
            }
            
            const result = await response.json();
            
            if (result.success) {
                return { success: true, message: 'Print sent to USB printer directly' };
            } else {
                // If server-side printing fails, return error instead of popup
                return { success: false, message: result.message || 'Failed to print to USB printer' };
            }
            
        } catch (error) {
            // If server-side printing fails, return error instead of popup
            console.error('Server-side USB printing failed:', error);
            return { success: false, message: 'Failed to print to USB printer: ' + error.message };
        }
    }
    
    /**
     * Print to USB device using browser popup (fallback)
     */
    async printToUSBPopup(device, printData) {
        try {
            // Create print window
            const printWindow = window.open('', '_blank', 'width=800,height=600');
            
            if (!printWindow) {
                throw new Error('Could not open print window. Please allow popups.');
            }
            
            // Generate print content
            const printContent = await this.generatePrintContent(printData);
            
            printWindow.document.write(printContent);
            printWindow.document.close();
            
            // Wait for print dialog
            printWindow.focus();
            
            // Auto-close after print
            setTimeout(() => {
                if (!printWindow.closed) {
                    printWindow.close();
                }
            }, 5000);
            
            return { success: true, message: 'Print job sent to browser (popup method)' };
            
        } catch (error) {
            throw error;
        }
    }
    
    /**
     * Generate print content
     */
    async generatePrintContent(printData) {
        // This would typically call a server endpoint to generate the print content
        const response = await fetch('ajax/generate_print_content.php', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(printData)
        });
        
        const result = await response.json();
        return result.content || '<html><body><p>Print content not available</p></body></html>';
    }
    
    
    /**
     * Get devices for specific print type
     * Prioritizes terminal-specific devices over global devices
     */
    getDevicesForType(printType) {
        // Get terminal ID for filtering
        const terminalId = this.getTerminalId();
        if (!this.devices) return [];
        
        const matchingDevices = this.devices.filter(device => 
            device.is_active == 1 && 
            (device.print_type === printType || device.print_type === 'all')
        );
        
        // If terminal ID is available, prioritize terminal-specific devices
        if (terminalId) {
            const terminalDevices = matchingDevices.filter(d => d.terminal_id == terminalId);
            const globalDevices = matchingDevices.filter(d => !d.terminal_id);
            // Return terminal-specific first, then global as fallback
            return [...terminalDevices, ...globalDevices];
        }
        
        // No terminal ID, return only global devices
        return matchingDevices.filter(d => !d.terminal_id);
    }
    
    /**
     * Get default device for print type
     */
    getDefaultDevice(printType) {
        const devices = this.getDevicesForType(printType);
        return devices.find(device => device.is_default == 1) || devices[0];
    }
    
    /**
     * Get device by ID
     */
    getDeviceById(deviceId) {
        if (!this.devices) return null;
        return this.devices.find(device => device.id == deviceId);
    }
    
    /**
     * Detect available printers
     */
    async detectPrinters() {
        // Try modern browser API first
        if ('navigator' in window && 'printer' in navigator) {
            try {
                const printers = await navigator.printer.getPrinters();
                return printers.map(printer => ({
                    name: printer.name,
                    status: printer.status || 'unknown'
                }));
            } catch (error) {
                console.error('Printer API failed:', error);
                // Fall through to fallback
            }
        }
        
        // Fallback: Return common printer names based on OS detection
        const commonPrinters = this.getCommonPrinters();
        console.log('Using fallback printer detection');
        return commonPrinters;
    }
    
    /**
     * Get common printer names based on system detection
     */
    getCommonPrinters() {
        const printers = [];
        const userAgent = navigator.userAgent.toLowerCase();
        
        // Only show the most common system printers, not a long list
        if (userAgent.includes('windows')) {
            printers.push(
                { name: 'Microsoft Print to PDF', status: 'available' },
                { name: 'Microsoft XPS Document Writer', status: 'available' }
            );
        } else if (userAgent.includes('mac')) {
            printers.push(
                { name: 'Save as PDF', status: 'available' }
            );
        } else if (userAgent.includes('linux')) {
            printers.push(
                { name: 'Print to File', status: 'available' }
            );
        }
        
        // Add only the most common thermal printers for POS systems
        printers.push(
            { name: 'Epson TM-T20', status: 'unknown' },
            { name: 'Star TSP143', status: 'unknown' }
        );
        
        return printers;
    }
    
    /**
     * Test printer connectivity
     */
    async testPrinter(deviceId) {
        try {
            const response = await fetch(`ajax/test_printer.php?device_id=${deviceId}`);
            const result = await response.json();
            return result;
        } catch (error) {
            return { success: false, message: error.message };
        }
    }
    
}

// Global print system instance
window.printSystem = new PrintSystem();

// Convenience functions for backward compatibility
window.handlePrint = (printType, printData, options) => {
    return window.printSystem.handlePrint(printType, printData, options);
};

window.showPrintDialog = (printType, printData, options) => {
    return window.printSystem.showPrintDialog(printType, printData, options);
};

window.autoPrint = (printType, printData, options) => {
    return window.printSystem.autoPrint(printType, printData, options);
};
