import express, { Request, Response } from "express";
import makeWASocket, {
    DisconnectReason,
    fetchLatestBaileysVersion,
    useMultiFileAuthState,
} from "@whiskeysockets/baileys";
import qrcode from "qrcode";
import { Boom } from "@hapi/boom";

let sock: ReturnType<typeof makeWASocket>;
let latestQR: string | null = null;

async function startWhatsApp() {
    const { state, saveCreds } = await useMultiFileAuthState("./auth");
    const { version } = await fetchLatestBaileysVersion();

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

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

    sock.ev.on("connection.update", (update) => {
        const { connection, qr, lastDisconnect } = update;
        if (qr) latestQR = qr;

        if (connection === "close") {
            const reason = (lastDisconnect?.error as Boom)?.output?.statusCode;
            console.log("Connection closed:", DisconnectReason[reason]);
            setTimeout(startWhatsApp, 1000);
        } else if (connection === "open") {
            console.log("Connected to WhatsApp");
            latestQR = null;
        }
    });
}

async function startServer() {
    const app = express();
    app.use(express.json());

    await startWhatsApp();

    app.get("/", async (_req: Request, res: Response): Promise<void> => {
        if (!latestQR) {
            res.status(503).send("QR code not yet generated");
            return;
        }
        try {
            const png = await qrcode.toBuffer(latestQR, { type: "png" });
            res.setHeader("Content-Type", "image/png");
            res.send(png);
        } catch {
            res.status(500).send("Failed to generate QR");
        }
    });

    app.post("/v1/messages", async (req: Request, res: Response): Promise<void> => {
        const { number, message } = req.body;
        if (!number || !message) {
            res.status(400).json({ error: "to and message are required" });
            return;
        }
        try {
            const jid = number.endsWith("@s.whatsapp.net") ? number : `${number}@s.whatsapp.net`;
            await sock.sendMessage(jid, { text: message, ephemeralExpiration: 0 });
            res.json({ success: true });
        } catch (err) {
            console.error("Send error:", err);
            res.status(500).json({ error: "Failed to send message" });
        }
    });

    app.post("/v1/session", async (_req: Request, res: Response): Promise<void> => {
        if (!sock?.user) {
            res.status(200).send("fail");
        } else {
            res.status(200).send("ok");
        }
    });

    const PORT = process.env.PORT || 3008;
    app.listen(PORT, () => console.log(`API listening on port ${PORT}`));
}

startServer().catch(console.error);
