require('dotenv').config();
const express = require('express');
const { Client, LocalAuth } = require('whatsapp-web.js');
const qrcode = require('qrcode-terminal');
const http = require('http');
const { Server } = require('socket.io');
const path = require('path');

const app = express();
const server = http.createServer(app);
const io = new Server(server, {
    path: '/proxy/whatsapp/socket.io',
    cors: { origin: "*" }
});

const PORT = process.env.PORT || 5001;

// Feature Flags
const ENABLE_INCOMING_MESSAGES = process.env.ENABLE_INCOMING_MESSAGES === 'true';
const ENABLE_AUTO_REPLY = process.env.ENABLE_AUTO_REPLY === 'true';

app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));

// Initialize WhatsApp Web Client with LocalAuth to persist session
const client = new Client({
    authStrategy: new LocalAuth({
        dataPath: './.wwebjs_auth'
    }),
    puppeteer: {
        headless: true,
        args: [
            '--no-sandbox', 
            '--disable-setuid-sandbox', 
            '--disable-dev-shm-usage',
            '--disable-gpu',
            '--disable-software-rasterizer',
            '--disable-extensions',
            '--no-zygote',
            '--single-process'
        ],
        protocolTimeout: 120000,
        timeout: 120000
    },
    webVersionCache: { type: 'none' }
});

let isReady = false;
let currentQr = null;

client.on('qr', (qr) => {
    currentQr = qr;
    console.log('\n[WhatsApp Bot] QR code generated. Scan via Dashboard or Terminal.');
    qrcode.generate(qr, { small: true });
    io.emit('qr', qr);
});

client.on('ready', () => {
    console.log('\n[WhatsApp Bot] Client is ready and authenticated!');
    isReady = true;
    currentQr = null;
    io.emit('ready', { ready: true });
});

client.on('auth_failure', (msg) => {
    console.error('[WhatsApp Bot] Authentication failure:', msg);
    io.emit('error', 'Authentication failure: ' + msg);
});

client.on('disconnected', (reason) => {
    console.log('[WhatsApp Bot] Client was logged out:', reason);
    isReady = false;
    currentQr = null;
    io.emit('disconnected', reason);
});

// Incoming messages handler
client.on('message', async msg => {
    if (ENABLE_INCOMING_MESSAGES) {
        console.log(`[WhatsApp Bot] Received message from ${msg.from}: ${msg.body}`);
        io.emit('incoming_message', { from: msg.from, body: msg.body });
    }
    
    if (ENABLE_AUTO_REPLY && !msg.fromMe) {
        if (msg.body.toLowerCase() === '!ping') {
            msg.reply('pong');
        }
    }
});

// Real-time connections
io.on('connection', (socket) => {
    socket.emit('status', {
        ready: isReady,
        authenticated: client.info ? true : false,
        qr: currentQr
    });
});

// ─── REST API ─────────────────────────────────────────────────────────────

app.get('/api/status', (req, res) => {
    res.json({
        service: 'whatsapp-gateway',
        ready: isReady,
        authenticated: client.info ? true : false
    });
});

// ─── App Tracking ───────────────────────────────────────────────────────────
const connectedApps = {};

function trackApp(req) {
    const appName = req.body.appName || req.headers['x-app-name'] || 'Unknown App';
    const ip = req.ip || req.connection.remoteAddress;
    
    if (!connectedApps[appName]) {
        connectedApps[appName] = {
            name: appName,
            firstSeen: new Date().toISOString(),
            lastSeen: new Date().toISOString(),
            messageCount: 0,
            lastIp: ip
        };
    }
    
    connectedApps[appName].lastSeen = new Date().toISOString();
    connectedApps[appName].messageCount += 1;
    connectedApps[appName].lastIp = ip;
}

app.get('/api/apps', (req, res) => {
    res.json({ success: true, apps: Object.values(connectedApps) });
});

const handleSendMessage = async (req, res) => {
    trackApp(req); // Track the app sending the request

    if (!isReady) {
        return res.status(503).json({ success: false, error: 'WhatsApp Web client is not ready. Please scan the QR code in the dashboard.' });
    }

    const { to, message } = req.body;
    if (!to || !message) {
        return res.status(400).json({ success: false, error: "Missing 'to' or 'message' fields." });
    }

    try {
        let targetJid = to;

        if (to.includes('chat.whatsapp.com') || /^[A-Za-z0-9]{20,24}$/.test(to)) {
            let inviteCode = to;
            if (to.includes('chat.whatsapp.com/')) {
                inviteCode = to.split('chat.whatsapp.com/')[1].split('?')[0].trim();
            }
            try {
                targetJid = await client.acceptInvite(inviteCode);
            } catch (err) {
                // If the bot is already in the group or invite code is invalid, it will fail here.
                // It might already be joined.
            }
        }

        if (!targetJid.includes('@') && !targetJid.includes('-')) {
            let cleanPhone = targetJid.replace('whatsapp:', '').replace(/[+\s()-]/g, '').trim();
            targetJid = `${cleanPhone}@c.us`;
        } else if (!targetJid.includes('@')) {
            targetJid = `${targetJid}@g.us`;
        }

        const response = await client.sendMessage(targetJid, message);
        res.json({ success: true, messageId: response.id._serialized, recipient: targetJid });

    } catch (error) {
        res.status(500).json({ success: false, error: error.message || error });
    }
};

app.post('/api/send-message', handleSendMessage);
// Legacy endpoint
app.post('/send-message', handleSendMessage);

app.get('/api/groups', async (req, res) => {
    if (!isReady) return res.status(503).json({ error: 'Not ready' });
    try {
        const chats = await client.getChats();
        const groups = chats.filter(c => c.isGroup);
        const groupData = groups.map(g => ({
            id: g.id._serialized,
            name: g.name,
            participants: g.participants ? g.participants.length : 0
        }));
        res.json({ success: true, groups: groupData });
    } catch (err) {
        res.status(500).json({ error: err.message });
    }
});

app.post('/api/groups/invite', async (req, res) => {
    if (!isReady) return res.status(503).json({ error: 'Not ready' });
    const { groupId } = req.body;
    try {
        const code = await client.groupGetInviteCode(groupId);
        res.json({ success: true, inviteLink: `https://chat.whatsapp.com/${code}` });
    } catch (err) {
        res.status(500).json({ error: err.message });
    }
});

app.post('/api/groups/create', async (req, res) => {
    if (!isReady) return res.status(503).json({ error: 'Not ready' });
    const { title, initialParticipants = [] } = req.body; // Needs standard WhatsApp JIDs
    try {
        const result = await client.createGroup(title, initialParticipants);
        res.json({ success: true, groupId: result.gid._serialized });
    } catch (err) {
        res.status(500).json({ error: err.message });
    }
});

server.listen(PORT, '0.0.0.0', () => {
    console.log(`[WhatsApp Gateway] Server running at http://0.0.0.0:${PORT}`);
});

console.log('[WhatsApp Bot] Initializing client...');
client.initialize();
