// Bluetooth Printer Controller for Classic Bluetooth (SPP) printers
// This handles printing via Classic Bluetooth which is not supported by Web Bluetooth API


// Try to load bluetooth-serial-port (may require native compilation)
let BluetoothSerialPort;
try {
  BluetoothSerialPort = require('bluetooth-serial-port').BluetoothSerialPort;
} catch (error) {
  console.warn('bluetooth-serial-port not available. Please install it: npm install bluetooth-serial-port');
  console.warn('Note: On Windows, you may need to install Windows Build Tools first: npm install --global windows-build-tools');
  BluetoothSerialPort = null;
}

// Store active connections
const activeConnections = new Map();

/**
 * Connect to Bluetooth printer and send print data
 * @param {string} deviceAddress - MAC address of the Bluetooth device (e.g., "00:11:22:33:44:55")
 * @param {Array} data - Array of bytes (ESC/POS commands)
 * @returns {Promise<Object>}
 */
async function printViaBluetooth(deviceAddress, data) {
  return new Promise((resolve, reject) => {
    if (!BluetoothSerialPort) {
      reject(new Error('Bluetooth serial port library not available. Please install bluetooth-serial-port package.'));
      return;
    }
    
    const btSerial = new BluetoothSerialPort();
    const connectionKey = deviceAddress.toLowerCase();
    
    // Check if already connected
    if (activeConnections.has(connectionKey)) {
      const existingConnection = activeConnections.get(connectionKey);
      try {
        // Convert array back to Buffer
        const buffer = Buffer.from(data);
        existingConnection.write(buffer, (err) => {
          if (err) {
            console.error('Write error:', err);
            // Remove from active connections if write fails
            activeConnections.delete(connectionKey);
            existingConnection.close();
            reject(new Error(`Failed to write to printer: ${err.message}`));
          } else {
            console.log('Print data sent successfully via existing connection');
            resolve({ success: true, message: 'Print job sent successfully' });
          }
        });
        return;
      } catch (error) {
        // If existing connection fails, remove it and create new one
        activeConnections.delete(connectionKey);
        existingConnection.close();
      }
    }

    // Find and connect to the device
    btSerial.findSerialPortChannel(deviceAddress, (channel) => {
      console.log(`Found channel ${channel} for device ${deviceAddress}`);
      
      btSerial.connect(deviceAddress, channel, () => {
        console.log('Connected to Bluetooth printer');
        
        // Store connection
        activeConnections.set(connectionKey, btSerial);
        
        // Convert array to Buffer
        const buffer = Buffer.from(data);
        
        // Send print data
        btSerial.write(buffer, (err) => {
          if (err) {
            console.error('Write error:', err);
            activeConnections.delete(connectionKey);
            btSerial.close();
            reject(new Error(`Failed to write to printer: ${err.message}`));
          } else {
            console.log('Print data sent successfully');
            // Keep connection open for potential future prints
            // Connection will be closed on disconnect or error
            resolve({ success: true, message: 'Print job sent successfully' });
          }
        });
      }, () => {
        // Connection failed
        const error = new Error('Failed to connect to Bluetooth device');
        console.error('Connection error:', error);
        reject(error);
      });
    }, (err) => {
      console.error('Error finding device:', err);
      reject(new Error(`Device not found or not accessible: ${err.message}`));
    });
  });
}

/**
 * Disconnect from Bluetooth printer
 */
function disconnectBluetooth(deviceAddress) {
  const connectionKey = deviceAddress.toLowerCase();
  if (activeConnections.has(connectionKey)) {
    const connection = activeConnections.get(connectionKey);
    connection.close();
    activeConnections.delete(connectionKey);
    console.log(`Disconnected from ${deviceAddress}`);
    return { success: true, message: 'Disconnected successfully' };
  }
  return { success: false, message: 'No active connection found' };
}

/**
 * Print receipt via Bluetooth
 * POST /api/bluetooth/print
 * Body: { deviceAddress: "00:11:22:33:44:55", data: [array of bytes] }
 */
exports.printReceipt = async (req, res) => {
  try {
    const { deviceAddress, data } = req.body;

    if (!deviceAddress) {
      return res.status(400).json({
        success: false,
        error: 'Device address (MAC address) is required'
      });
    }

    if (!data || !Array.isArray(data)) {
      return res.status(400).json({
        success: false,
        error: 'Print data (array of bytes) is required'
      });
    }

    console.log(`Print request received for device: ${deviceAddress}`);
    console.log(`Data size: ${data.length} bytes`);

    const result = await printViaBluetooth(deviceAddress, data);
    
    res.status(200).json(result);
  } catch (error) {
    console.error('Bluetooth print error:', error);
    res.status(500).json({
      success: false,
      error: error.message || 'Failed to print via Bluetooth'
    });
  }
};

/**
 * Disconnect from Bluetooth printer
 * POST /api/bluetooth/disconnect
 * Body: { deviceAddress: "00:11:22:33:44:55" }
 */
exports.disconnect = (req, res) => {
  try {
    const { deviceAddress } = req.body;

    if (!deviceAddress) {
      return res.status(400).json({
        success: false,
        error: 'Device address is required'
      });
    }

    const result = disconnectBluetooth(deviceAddress);
    res.status(200).json(result);
  } catch (error) {
    console.error('Disconnect error:', error);
    res.status(500).json({
      success: false,
      error: error.message || 'Failed to disconnect'
    });
  }
};

/**
 * Health check endpoint
 * GET /api/bluetooth/health
 */
exports.health = (req, res) => {
  res.status(200).json({
    success: true,
    message: 'Bluetooth printer service is running',
    activeConnections: activeConnections.size
  });
};

