import pkg, { DisconnectReason } from '@whiskeysockets/baileys';
import pino from 'pino';
import mqtt from 'mqtt';
import fs from 'fs';

const {
  makeWASocket,
  useMultiFileAuthState,
  fetchLatestBaileysVersion,
} = pkg;

const allowedNumbers = [
  '62882009051780@s.whatsapp.net',
  '6287862977046@s.whatsapp.net',
  '6289521851079@s.whatsapp.net',
];

// Status lokal perabotan (backup jika diperlukan)
const status = {
  'lampu kamar': false,
  'lampu teras': false,
  'kipas': false,
  'pintu': false,
};

// Penyimpan siapa yang meminta status
const pendingStatusRequests = {};

// Fungsi konversi status jadi teks

function getStatusString(statusObj) {
  return Object.entries(statusObj)
    .map(([device, value]) => {
      if (device === 'pintu') {
        return `- ${device} : ${value === 'dibuka' ? '🔓 Dibuka' : '🔒 Dikunci'}`;
      } else {
        return `- ${device} : ${value === true || value === 'true' ? '✅ Menyala' : '❌ Mati'}`;
      }
    })
    .join('\n');

// MQTT setup
const mqttClient = mqtt.connect('mqtt://test.mosquitto.org');

mqttClient.on('connect', () => {
  console.log('📡 Terhubung ke MQTT broker: test.mosquitto.org');
});

mqttClient.on('error', (err) => {
  console.error('❌ MQTT Error:', err);
});

// Tangani balasan dari ESP32 ke topik status
mqttClient.on('message', async (topic, message) => {
  if (topic === 'cristine/status') {
    try {
      const parsedStatus = JSON.parse(message.toString());
      const now = Date.now();

      for (const [jid, time] of Object.entries(pendingStatusRequests)) {
        if (now - time <= 10000) { // valid 10 detik
          await sock.sendMessage(jid, {
            text: `📊 Status Real-time:\n${getStatusString(parsedStatus)}`
          });
        }
      }

      // Kosongkan request setelah dibalas
      for (const jid of Object.keys(pendingStatusRequests)) {
        delete pendingStatusRequests[jid];
      }
    } catch (e) {
      console.error('❌ Gagal parsing status dari ESP32:', e);
    }
  }
});

mqttClient.subscribe('cristine/status');

// Fungsi utama bot
let sock;
async function startBot() {
  const { version } = await fetchLatestBaileysVersion();
  const { state, saveCreds } = await useMultiFileAuthState('./auth_info_baileys');

  sock = makeWASocket({
    version,
    auth: state,
    printQRInTerminal: true,
    logger: pino({ level: 'silent' }),
  });

  sock.ev.on('creds.update', saveCreds);

  sock.ev.on('connection.update', async ({ connection, lastDisconnect }) => {
    if (connection === 'close') {
      const reasonCode = lastDisconnect?.error?.output?.statusCode;
      const isLoggedOut = reasonCode === DisconnectReason.loggedOut;

      console.log('⚠️ Koneksi terputus:', reasonCode);

      if (isLoggedOut) {
        fs.rmSync('./auth_info_baileys', { recursive: true, force: true });
        console.log('🔁 Silakan restart untuk login ulang.');
      } else {
        startBot();
      }
    }

    if (connection === 'open') {
      console.log('✅ Bot WhatsApp berhasil online!');
    }
  });

  sock.ev.on('messages.upsert', async ({ messages }) => {
    const msg = messages[0];
    if (!msg.message || msg.key.fromMe) return;

    const sender = msg.key.remoteJid;
    if (!allowedNumbers.includes(sender)) return;

    const text =
      msg.message.conversation ||
      msg.message?.extendedTextMessage?.text ||
      msg.message?.imageMessage?.caption ||
      msg.message?.buttonsResponseMessage?.selectedButtonId ||
      msg.message?.listResponseMessage?.singleSelectReply?.selectedRowId;

    if (!text) return;
    const command = text.trim().toLowerCase();
    console.log(`📩 Pesan dari ${sender}:`, command);

    switch (command) {
      case 'menu':
        await sock.sendMessage(sender, {
          text: '📋 Menu Kontrol:\n' +
            '- nyalakan lampu kamar\n' +
            '- matikan lampu kamar\n' +
            '- nyalakan lampu teras\n' +
            '- matikan lampu teras\n' +
            '- nyalakan kipas\n' +
            '- matikan kipas\n' +
            '- buka pintu\n' +
            '- kunci pintu\n' +
            '- status',
        });
        break;

      case 'nyalakan lampu kamar':
        status['lampu kamar'] = true;
        mqttClient.publish('cristine/control/lampu_kamar', 'ON');
        await sock.sendMessage(sender, { text: '💡 Lampu kamar *dinyalakan*.' });
        break;

      case 'matikan lampu kamar':
        status['lampu kamar'] = false;
        mqttClient.publish('cristine/control/lampu_kamar', 'OFF');
        await sock.sendMessage(sender, { text: '💡 Lampu kamar *dimatikan*.' });
        break;

      case 'nyalakan lampu teras':
        status['lampu teras'] = true;
        mqttClient.publish('cristine/control/lampu_teras', 'ON');
        await sock.sendMessage(sender, { text: '💡 Lampu teras *dinyalakan*.' });
        break;

      case 'matikan lampu teras':
        status['lampu teras'] = false;
        mqttClient.publish('cristine/control/lampu_teras', 'OFF');
        await sock.sendMessage(sender, { text: '💡 Lampu teras *dimatikan*.' });
        break;

      case 'nyalakan kipas':
        status['kipas'] = true;
        mqttClient.publish('cristine/control/kipas', 'ON');
        await sock.sendMessage(sender, { text: '🌀 Kipas *dinyalakan*.' });
        break;

      case 'matikan kipas':
        status['kipas'] = false;
        mqttClient.publish('cristine/control/kipas', 'OFF');
        await sock.sendMessage(sender, { text: '🌀 Kipas *dimatikan*.' });
        break;

      case 'buka pintu':
        status['pintu'] = true;
        mqttClient.publish('cristine/control/pintu', 'ON');
        await sock.sendMessage(sender, { text: '🚪 Pintu *dibuka*.' });
        break;

      case 'kunci pintu':
        status['pintu'] = false;
        mqttClient.publish('cristine/control/pintu', 'OFF');
        await sock.sendMessage(sender, { text: '🚪 Pintu *dikunci*.' });
        break;

      case 'status':
        pendingStatusRequests[sender] = Date.now();
        mqttClient.publish('cristine/request/status', 'REQUEST');
        await sock.sendMessage(sender, { text: '⏳ Meminta status dari perangkat, mohon tunggu...' });
        break;

      default:
        await sock.sendMessage(sender, {
          text: `⚠️ Perintah tidak dikenali.\nKetik *menu* untuk melihat daftar perintah.`
        });
        break;
    }
  });
}
}
startBot();
