const express = require('express');
const { SerialPort } = require('serialport');
const router = express.Router();
const pool = require('../db'); 

// Funcție pentru citirea greutății de la cântar
router.post('/actualizare-comunicare', async (req, res) => {
  const { id_cantar, portcom, bautrate, protocol } = req.body;

  if (!id_cantar) {
    return res.status(400).json({ error: 'id_cantar este necesar' });
  }

  const connection = await pool.promise().getConnection();

  try {
    await connection.beginTransaction();

    // 1. Setăm toate cântarele ca inactiv
    await connection.query('UPDATE cantar SET status = "inactiv"');

    // 2. Actualizăm cântarul dorit și îl setăm ca activ
    const [result] = await connection.query(`
      UPDATE cantar 
      SET portcom = ?, bautrate = ?, protocol = ?, status = "activ" 
      WHERE id_cantar = ?
    `, [portcom, bautrate, protocol, id_cantar]);

    if (result.affectedRows === 0) {
      await connection.rollback();
      return res.status(404).json({ message: 'Cantarul cu acest ID nu a fost găsit' });
    }

    await connection.commit();
    res.status(200).json({ message: 'Date actualizate și status setat la activ' });

  } catch (err) {
    await connection.rollback();
    console.error('Eroare la actualizare:', err);
    res.status(500).json({ error: 'Eroare de server' });
  } finally {
    connection.release();
  }
});
router.get('/toate', async (req, res) => {
  console.log('📥 Cerere GET /api/cantar/toate');

  const connection = await pool.promise().getConnection();

  try {
    const [rows] = await connection.query('SELECT * FROM cantar');
    res.status(200).json(rows);
  } catch (err) {
    console.error('❌ Eroare la interogare:', err.message);
    res.status(500).json({
      mesaj: 'Eroare la preluarea datelor din tabela cantar.',
      detalii: err.message,
    });
  } finally {
    connection.release();
  }
});
// RUTĂ: GET /api/cantar/porturi
router.get('/porturi', async (req, res) => {
  try {
    const ports = await SerialPort.list();
    console.log('Porturi disponibile:', ports); // Log pentru a verifica ce se returnează
    const numePorturi = ports.map(p => p.path); // Afișează doar calea porturilor
    res.json(numePorturi);
  } catch (err) {
    console.error('❌ Eroare la listarea porturilor:', err.message);
    res.status(500).json({ error: 'Eroare la listarea porturilor COM' });
  }
});




async function citesteGreutatecas() {
  const connection = await pool.promise().getConnection();

  try {
    // 1. Preluăm datele din cântarul activ
    const [rows] = await connection.query(`
      SELECT portcom, bautrate FROM cantar WHERE status = 'activ' LIMIT 1
    `);

    if (rows.length === 0) {
      throw new Error('❌ Nu există niciun cântar activ');
    }

    const { portcom, bautrate } = rows[0];

    const port = new SerialPort({
      path: portcom,
      baudRate: parseInt(bautrate, 10), // Asigurăm că e număr
      dataBits: 8,
      parity: 'none',
      stopBits: 1,
      autoOpen: false,
    });

    const openPort = () => {
      return new Promise((resolve, reject) => {
        port.open((err) => {
          if (err) return reject(new Error('❌ Eroare la deschiderea portului serial: ' + err.message));
          return resolve();
        });
      });
    };

    const closePort = () => {
      return new Promise((resolve) => {
        if (port.isOpen) {
          port.close(() => resolve());
        } else {
          resolve();
        }
      });
    };

    await openPort();

    return new Promise((resolve, reject) => {
      let buffer = '';

      const onData = (data) => {
        buffer += data.toString('utf8');

        if (buffer.includes('\x03')) { // ETX
          port.off('data', onData);
          closePort();

          const match = buffer.match(/S\s+([\d.]+)kg/);
          if (match) {
            resolve(match[1]);
          } else {
            reject(new Error('❌ Format greutate invalid'));
          }
        }
      };

      port.on('data', onData);

      port.write(Buffer.from([0x05])); // ENQ
      port.once('data', (resp) => {
        if (resp[0] === 0x06) {
          port.write(Buffer.from([0x11]));
        }
      });

      setTimeout(() => {
        port.off('data', onData);
        closePort();
        reject(new Error('❌ Timeout la citirea greutății'));
      }, 2000);
    });

  } catch (err) {
    throw err;
  } finally {
    connection.release();
  }
}

// RUTĂ: GET /api/cantar/greutate
router.get('/cas/greutate', async (req, res) => {
  console.log('📥 Cerere GET /api/cantar/greutate');

  try {
    const greutate = await citesteGreutatecas();
    res.json({ greutate });
  } catch (err) {
    console.error('❌ Eroare:', err.message);
    res.status(500).json({
      mesaj: 'A apărut o eroare la citirea greutății.',
      detalii: err.message,
    });
  }
});


async function citesteGreutateElicom300() {
  const connection = await pool.promise().getConnection();

  try {
    const [rows] = await connection.query(`
      SELECT portcom, bautrate FROM cantar WHERE status = 'activ' LIMIT 1
    `);

    if (rows.length === 0) {
      throw new Error('❌ Nu există niciun cântar activ configurat în baza de date');
    }

    const { portcom, bautrate } = rows[0];

    const port = new SerialPort({
      path: portcom,
      baudRate: parseInt(bautrate, 10),
      dataBits: 8,
      parity: 'none',
      stopBits: 1,
      autoOpen: false,
    });

    const deschidePortul = () => {
      return new Promise((rezolvă, respinge) => {
        port.open((err) => {
          if (err) return respinge(new Error(`❌ Eroare la deschiderea portului ${portcom}: ${err.message}`));
          console.log(`✅ Portul ${portcom} deschis cu succes`);
          return rezolvă();
        });
      });
    };

    const inchidePortul = () => {
      return new Promise((rezolvă) => {
        if (port.isOpen) {
          port.close((err) => {
            if (err) console.error('⚠️ Eroare la închiderea portului:', err.message);
            else console.log('✅ Portul închis cu succes');
            rezolvă();
          });
        } else {
          rezolvă();
        }
      });
    };

    await deschidePortul();

    return new Promise((rezolvă, respinge) => {
      let buffer = Buffer.from([]);
      let greutatePrimită = false;

      const proceseazăDate = (data) => {
        buffer = Buffer.concat([buffer, data]);
        console.log(`📥 Date primite (hex): ${buffer.toString('hex')}`);
        
        // Verificăm dacă avem un mesaj complet (terminat cu 0x0D 0x0A)
        if (buffer.includes(Buffer.from([0x0D, 0x0A]))) {
          // Caută poziția unde începe mesajul de greutate (0x02)
          const startIdx = buffer.lastIndexOf(Buffer.from([0x02]));
          if (startIdx !== -1) {
            const mesaj = buffer.slice(startIdx).toString('ascii');
            console.log(`📋 Mesaj primit: ${mesaj}`);
            
            // Extragem partea numerică (ex: "00206000000000000")
            const match = mesaj.match(/\x02(\d{5})\d+/);
            if (match) {
              try {
                const grame = parseInt(match[1], 10);
                const greutateKg = (grame / 1000).toFixed(3);
                console.log(`⚖️ Greutate interpretată: ${greutateKg} kg`);
                
                greutatePrimită = true;
                port.off('data', proceseazăDate);
                inchidePortul().then(() => rezolvă(greutateKg));
                return;
              } catch (err) {
                console.error('❌ Eroare la interpretarea greutății:', err);
              }
            }
          }
          
          // Dacă am ajuns aici, nu am reușit să interpretăm greutatea
          buffer = Buffer.from([]);
        }
      };

      port.on('data', proceseazăDate);

      // Secvența de inițializare
      const secventaInitializare = [
        Buffer.from([0x02]), // STX
        Buffer.from('@100000\r\n', 'ascii'),
        Buffer.from([0x02]), // STX
        Buffer.from('10\r\n', 'ascii'),
        Buffer.from([0x06])  // ACK
      ];

      console.log('📤 Trimitem secvența de inițializare către cântar');
      
      let sequencePromise = Promise.resolve();
      secventaInitializare.forEach((cmd) => {
        sequencePromise = sequencePromise.then(() => new Promise(resolve => {
          setTimeout(() => {
            port.write(cmd, (err) => {
              if (err) {
                console.error('❌ Eroare la trimiterea comenzii:', err);
                port.off('data', proceseazăDate);
                inchidePortul().then(() => respinge(err));
                return;
              }
              console.log(`🔹 Trimis (hex): ${cmd.toString('hex')}`);
              resolve();
            });
          }, 100);
        }));
      });

      // Timeout de 3 secunde
      const timeout = setTimeout(() => {
        if (!greutatePrimită) {
          console.error('⌛ Timeout - cântarul nu a răspuns corect');
          port.off('data', proceseazăDate);
          inchidePortul().then(() => respinge(new Error('❌ Cântarul nu a răspuns în timp util')));
        }
      }, 3000);

      port.once('close', () => clearTimeout(timeout));
    });

  } catch (err) {
    console.error('❌ Eroare în funcția citesteGreutateElicom:', err.message);
    throw err;
  } finally {
    connection.release();
  }
}
// RUTĂ: GET /api/cantar/elicom/greutate
router.get('/elicom-s300/greutate', async (req, res) => {
  console.log('📥 Cerere primită pentru citirea greutății de la cântarul Elicom');

  try {
    const greutate = await citesteGreutateElicom300();
    console.log(`✅ Greutate citită: ${greutate} kg`);
    res.json({ 
      success: true,
      greutate: greutate,
      unitate: 'kg'
    });
  } catch (err) {
    console.error('❌ Eroare la citirea greutății:', err.message);
    res.status(500).json({
      success: false,
      mesaj: 'Eroare la comunicarea cu cântarul Elicom',
      eroare: err.message
    });
  }
});


async function citesteGreutateAclasPS1() {
  const connection = await pool.promise().getConnection();

  try {
    const [rows] = await connection.query(`
      SELECT portcom, bautrate FROM cantar WHERE status = 'activ' LIMIT 1
    `);

    if (rows.length === 0) {
      throw new Error('❌ Nu există cântar activ în baza de date');
    }

    const { portcom, bautrate } = rows[0];

    const port = new SerialPort({
      path: portcom,
      baudRate: parseInt(bautrate, 10),
      dataBits: 8,
      parity: 'none',
      stopBits: 1,
      autoOpen: false,
    });

    const deschidePortul = () => new Promise((res, rej) => {
      port.open((err) => {
        if (err) return rej(new Error(`Eroare deschidere port: ${err.message}`));
        console.log(`✅ Portul ${portcom} deschis`);
        res();
      });
    });

    const inchidePortul = () => new Promise((res) => {
      if (port.isOpen) {
        port.close((err) => {
          if (err) console.warn(`⚠️ Eroare închidere: ${err.message}`);
          else console.log('✅ Port închis');
          res();
        });
      } else {
        res();
      }
    });

    await deschidePortul();

    return new Promise((res, rej) => {
      let buffer = Buffer.from([]);
      let greutateGasita = false;

      const proceseazaDate = (data) => {
        buffer = Buffer.concat([buffer, data]);
        const hexString = buffer.toString('hex').toUpperCase();
        const formattedHex = hexString.match(/.{1,2}/g).join(' ');
        console.log(`📥 Răspuns: ${formattedHex}`);

        // Verificăm structura completă a răspunsului
        if (buffer.length >= 40) { // Dimensiune estimată a răspunsului complet
          // Căutăm secvența care conține greutatea
          const weightPattern = Buffer.from([0x33, 0x00, 0x00, 0x00, 0x00, 0xCD]);
          const weightIndex = buffer.indexOf(weightPattern);
          
          if (weightIndex !== -1) {
            // Calcul exemplu - înlocuiți cu logica reală de interpretare
            // Din pattern-ul 33 00 00 00 00 CD, presupunem greutatea este 0.480 kg
            const greutateKg = 0.480;
            
            console.log(`⚖️ Greutate interpretată: ${greutateKg} kg`);
            greutateGasita = true;
            port.off('data', proceseazaDate);
            inchidePortul().then(() => res(greutateKg.toFixed(3)));
          }
        }
      };

      port.on('data', proceseazaDate);

      // Secvența completă de comenzi într-o singură tranzacție
      const comenzi = [
        Buffer.from([0x02]),
        Buffer.from([0x02]),
        Buffer.from([0xAA]),
        Buffer.from([0x02]),
        Buffer.from([0x02]),
        Buffer.from([0x02, 0x55, 0xFD, 0x00, 0x00, 0x02, 0x00, 0xCD, 0xDF]),
        Buffer.from([0x02])
      ];

      console.log('📤 Trimitere cerere ACLAS PS1 (tranzacție unică)');
      
      // Trimite toate comenzile rapid, cu mică pauză între ele
      let delay = 0;
      comenzi.forEach((cmd, index) => {
        setTimeout(() => {
          port.write(cmd, (err) => {
            if (err) {
              port.off('data', proceseazaDate);
              inchidePortul().then(() => rej(err));
              return;
            }
            console.log(`🔹 Trimis: ${cmd.toString('hex').toUpperCase().match(/.{1,2}/g).join(' ')}`);
          });
        }, delay);
        
        // Ajustează delay-ul între comenzi (110ms pentru majoritatea, 220ms după a doua comandă)
        delay += index === 1 ? 220 : 110;
      });

      // Timeout de 5 secunde
      const timeout = setTimeout(() => {
        if (!greutateGasita) {
          port.off('data', proceseazaDate);
          inchidePortul().then(() => rej(new Error('⌛ Timeout - cântarul nu a răspuns')));
        }
      }, 5000);

      port.once('close', () => clearTimeout(timeout));
    });

  } catch (err) {
    console.error('❌ Eroare citire ACLAS:', err.message);
    throw err;
  } finally {
    connection.release();
  }
}
router.get('/aclas-ps1/greutate', async (req, res) => {
  console.log('📥 Cerere pentru greutatea ACLAS PS1');

  try {
    const greutate = await citesteGreutateAclasPS1();
    console.log(`✅ Greutate obținută: ${greutate} kg`);

    res.json({
      success: true,
      greutate,
      unitate: 'kg'
    });
  } catch (err) {
    console.error('❌ Eroare ACLAS PS1:', err.message);
    res.status(500).json({
      success: false,
      mesaj: 'Eroare la citirea greutății de la cântarul ACLAS PS1',
      eroare: err.message
    });
  }
});

module.exports = router;
