// NOTE: auth/ directory is in .gitignore — do not commit session data

const { default: makeWASocket, useMultiFileAuthState, DisconnectReason, fetchLatestBaileysVersion } = require('@whiskeysockets/baileys');
const express = require('express');
const pino = require('pino');
const QRCode = require('qrcode');
const path = require('path');

const PORT = 8098;
const HOST = '0.0.0.0';
const AUTH_DIR = path.join(__dirname, 'auth');
const MAX_RECONNECT_ATTEMPTS = 5;

const logger = pino({ level: 'warn' });

let sock = null;
let connected = false;
let phoneNumber = null;
let currentQR = null;
let currentPairingCode = null;
let reconnectAttempts = 0;
let messageQueue = [];
let shuttingDown = false;

// --- WhatsApp connection ---

async function startConnection() {
  const { state, saveCreds } = await useMultiFileAuthState(AUTH_DIR);
  const { version } = await fetchLatestBaileysVersion();

  sock = makeWASocket({
    version,
    auth: state,
    logger,
    printQRInTerminal: false,
    defaultQueryTimeoutMs: 60000,
  });

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

  sock.ev.on('connection.update', async (update) => {
    const { connection, lastDisconnect, qr } = update;

    if (qr) {
      try {
        currentQR = await QRCode.toDataURL(qr);
        console.log('[whatsapp] QR code generated — scan with WhatsApp to link');
      } catch (err) {
        console.error('[whatsapp] Failed to generate QR code:', err.message);
      }
    }

    if (connection === 'open') {
      connected = true;
      currentQR = null;
      reconnectAttempts = 0;
      phoneNumber = sock.user?.id?.split(':')[0] || sock.user?.id?.split('@')[0] || null;
      console.log(`[whatsapp] Connected as ${phoneNumber}`);
    }

    if (connection === 'close') {
      connected = false;
      phoneNumber = null;
      const statusCode = lastDisconnect?.error?.output?.statusCode;
      const shouldReconnect = statusCode !== DisconnectReason.loggedOut;

      console.log(`[whatsapp] Disconnected (status: ${statusCode})`);

      if (shouldReconnect && !shuttingDown) {
        if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
          reconnectAttempts++;
          const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 30000);
          console.log(`[whatsapp] Reconnecting in ${delay}ms (attempt ${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`);
          setTimeout(startConnection, delay);
        } else {
          console.error(`[whatsapp] Max reconnect attempts reached (${MAX_RECONNECT_ATTEMPTS})`);
        }
      } else if (statusCode === DisconnectReason.loggedOut) {
        console.log('[whatsapp] Logged out — delete auth/ and restart to re-link');
      }
    }
  });

  sock.ev.on('messages.upsert', ({ messages, type }) => {
    if (type !== 'notify') return;

    for (const msg of messages) {
      // Skip status broadcasts
      if (msg.key.remoteJid === 'status@broadcast') continue;
      // Skip own messages in private chats (allow in groups for self-chat)
      const isGroup = msg.key.remoteJid.endsWith('@g.us');
      if (msg.key.fromMe && !isGroup) continue;
      // Only text messages
      const text = msg.message?.conversation || msg.message?.extendedTextMessage?.text;
      if (!text) continue;

      messageQueue.push({
        from: msg.key.remoteJid,
        participant: msg.key.participant || null,
        pushName: msg.pushName || null,
        text,
        timestamp: msg.messageTimestamp,
        id: msg.key.id,
        isGroup,
        fromMe: msg.key.fromMe || false,
      });

      console.log(`[whatsapp] Message from ${msg.pushName || 'unknown'} in ${msg.key.remoteJid}: ${text.substring(0, 80)}`);
    }
  });
}

// --- Express API ---

const app = express();
app.use(express.json({ limit: '50mb' }));

app.get('/status', (_req, res) => {
  res.json({
    connected,
    phone: phoneNumber,
    qr: connected ? null : currentQR,
  });
});

app.post('/pair', async (req, res) => {
  if (connected) {
    return res.json({ error: 'already connected' });
  }
  const { phone } = req.body || {};
  if (!phone) {
    return res.status(400).json({ error: 'missing "phone" in body' });
  }
  if (!sock) {
    return res.status(503).json({ error: 'socket not ready yet, try again in a few seconds' });
  }
  try {
    const code = await sock.requestPairingCode(phone.replace(/\D/g, ''));
    currentPairingCode = code;
    console.log(`[whatsapp] Pairing code for ${phone}: ${code}`);
    res.json({ ok: true, code });
  } catch (err) {
    console.error('[whatsapp] Pairing code error:', err.message);
    res.status(500).json({ error: err.message });
  }
});

app.get('/pair-code', (_req, res) => {
  if (connected) return res.json({ error: 'already connected' });
  if (!currentPairingCode) return res.json({ error: 'no pairing code yet — POST /pair first' });
  res.json({ code: currentPairingCode });
});

app.get('/qr', (_req, res) => {
  if (connected) {
    return res.json({ error: 'already connected' });
  }
  if (!currentQR) {
    return res.json({ error: 'no QR code available yet' });
  }
  // Return as HTML page with QR image for easy scanning
  const html = `<!DOCTYPE html>
<html><head><title>WhatsApp QR</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<style>body{display:flex;justify-content:center;align-items:center;min-height:100vh;margin:0;background:#111;flex-direction:column;font-family:sans-serif;color:#fff}
img{width:400px;height:400px;border-radius:12px}p{margin-top:16px;opacity:.6}</style></head>
<body><img src="${currentQR}" alt="QR Code"/><p>Scan with WhatsApp &rarr; Linked Devices</p></body></html>`;
  res.type('html').send(html);
});

app.post('/send', async (req, res) => {
  const { to, text } = req.body || {};

  if (!to || !text) {
    return res.status(400).json({ ok: false, error: 'missing "to" or "text" in body' });
  }
  if (!connected || !sock) {
    return res.status(503).json({ ok: false, error: 'not connected to WhatsApp' });
  }

  try {
    const result = await sock.sendMessage(to, { text });
    res.json({ ok: true, id: result.key.id });
  } catch (err) {
    console.error('[whatsapp] Send failed:', err.message);
    res.status(500).json({ ok: false, error: err.message });
  }
});

app.post('/send-document', async (req, res) => {
  const { to, filename, mimetype, data_base64, caption } = req.body || {};
  if (!to || !filename || !data_base64) {
    return res.status(400).json({ ok: false, error: 'missing "to", "filename", or "data_base64"' });
  }
  if (!connected || !sock) {
    return res.status(503).json({ ok: false, error: 'not connected to WhatsApp' });
  }
  try {
    const buffer = Buffer.from(data_base64, 'base64');
    const result = await sock.sendMessage(to, {
      document: buffer,
      fileName: filename,
      mimetype: mimetype || 'application/octet-stream',
      caption: caption || '',
    });
    res.json({ ok: true, id: result.key.id });
  } catch (err) {
    console.error('[whatsapp] Send document failed:', err.message);
    res.status(500).json({ ok: false, error: err.message });
  }
});

app.post('/react', async (req, res) => {
  const { to, id, emoji, fromMe, participant } = req.body || {};

  if (!to || !id || emoji == null) {
    return res.status(400).json({ ok: false, error: 'missing "to", "id", or "emoji" in body' });
  }
  if (!connected || !sock) {
    return res.status(503).json({ ok: false, error: 'not connected to WhatsApp' });
  }

  try {
    const key = { remoteJid: to, id, fromMe: fromMe || false };
    if (participant) key.participant = participant;
    await sock.sendMessage(to, { react: { text: emoji, key } });
    res.json({ ok: true });
  } catch (err) {
    console.error('[whatsapp] React failed:', err.message);
    res.status(500).json({ ok: false, error: err.message });
  }
});

app.get('/messages', (_req, res) => {
  const messages = messageQueue.splice(0);
  res.json({ messages });
});

// --- Startup ---

const server = app.listen(PORT, HOST, () => {
  console.log(`[whatsapp] Bridge API listening on http://${HOST}:${PORT}`);
  startConnection().catch((err) => {
    console.error('[whatsapp] Failed to start connection:', err.message);
  });
});

// --- Graceful shutdown ---

function shutdown(signal) {
  console.log(`[whatsapp] Received ${signal}, shutting down...`);
  shuttingDown = true;
  if (sock) {
    sock.end(undefined);
  }
  server.close(() => {
    console.log('[whatsapp] HTTP server closed');
    process.exit(0);
  });
  // Force exit after 5s
  setTimeout(() => process.exit(1), 5000);
}

process.on('SIGTERM', () => shutdown('SIGTERM'));
process.on('SIGINT', () => shutdown('SIGINT'));
