/**
 * @file confirmThenEnqueueMessage.cpp
 * @brief Member function of the UI_Constructor class.
 * Handles autoreply confirmation via both local UI notification and
 * the network API, ensuring the operator and external clients are
 * kept in sync on pending autoreply transmissions.
 * @ingroup API Network Message API
 */

#include "../JS8_UI/mainwindow.h"

/**
 * @brief Presents a local confirmation dialog and fires a network confirmation request.
 *
 * Called from the decoder thread; all Qt and network operations are marshalled
 * to the GUI thread via QMetaObject::invokeMethod. A SelfDestructMessageBox is
 * shown to the local operator while simultaneously sending
 * STATION.AUTOREPLY_CONFIRM_REQUEST to any connected API clients.
 *
 * Whichever resolves first — local operator response or timeout — cancels the
 * other. On acceptance, enqueueMessage() is called and
 * STATION.AUTOREPLY_CONFIRM_ACCEPTED is sent. On rejection or timeout,
 * STATION.AUTOREPLY_CONFIRM_EXPIRED is sent.
 *
 * @param timeout  Seconds before the confirmation auto-rejects.
 * @param priority Transmission priority passed to enqueueMessage().
 * @param message  The autoreply message text shown to the operator and sent over the API.
 * @param offset   Frequency offset passed to enqueueMessage().
 * @param c        Callback passed to enqueueMessage() on acceptance.
 *
 * @note Requires @ref PendingConfirmation::box to be present in the struct.
 * @note API 2.6+
 */
void UI_Constructor::confirmThenEnqueueMessage(int timeout, int priority,
                                               QString message, int offset,
                                               Callback c) {
    // CRITICAL: called from decoder thread → QTimer/sendNetworkMessage must run in GUI thread
    QMetaObject::invokeMethod(this, [this, timeout, priority, message, offset, c]() {
        int id = m_nextConfirmId++;

        // Timer auto-reject after timeout
        QTimer *timer = new QTimer(this);
        timer->setSingleShot(true);
        connect(timer, &QTimer::timeout, this, [this, id]() {
            if (m_pendingConfirmations.contains(id)) {
                auto pc = m_pendingConfirmations.take(id);
                pc.timer->deleteLater();
                sendNetworkMessage("STATION.AUTOREPLY_CONFIRM_EXPIRED", "",
                    {{"_ID", QVariant(-1)},
                     {"CONFIRM_ID", QVariant(id)},
                     {"MESSAGE", QVariant(pc.message)}});
                pc.box->close();
            }
        });

        // Local popup — same timeout as the network timer
        SelfDestructMessageBox *m = new SelfDestructMessageBox(
            timeout, "Autoreply Confirmation Required",
            QString("A transmission is queued for autoreply:\n\n%1\n\nWould you "
                    "like to send this transmission?")
                .arg(message),
            QMessageBox::Question, QMessageBox::Yes | QMessageBox::No,
            QMessageBox::No, false, this);
        m->setWindowModality(Qt::NonModal);

        // Build and insert the PendingConfirmation before any signals can fire
        PendingConfirmation pc;
        pc.id       = id;
        pc.priority = priority;
        pc.message  = message;
        pc.offset   = offset;
        pc.callback = c;
        pc.timer    = timer;
        pc.box      = m;
        m_pendingConfirmations.insert(id, pc);

        // Local operator response
        connect(m, &SelfDestructMessageBox::finished, this,
            [this, m, id](int) {
                m->deleteLater();

                if (!m_pendingConfirmations.contains(id))
                    return; // already resolved by timer

                auto pc = m_pendingConfirmations.take(id);
                pc.timer->stop();
                pc.timer->deleteLater();

                if (m->result() == QMessageBox::Yes) {
                    enqueueMessage(pc.priority, pc.message, pc.offset, pc.callback);
                    sendNetworkMessage("STATION.AUTOREPLY_CONFIRM_ACCEPTED", pc.message,
                        {{"_ID", QVariant(-1)},
                         {"CONFIRM_ID", QVariant(id)},
                         {"PRIORITY", QVariant(pc.priority)},
                         {"OFFSET", QVariant(pc.offset)}});
                } else {
                    sendNetworkMessage("STATION.AUTOREPLY_CONFIRM_EXPIRED", "",
                        {{"_ID", QVariant(-1)},
                         {"CONFIRM_ID", QVariant(id)},
                         {"MESSAGE", QVariant(pc.message)}});
                }
            });

        // Both show() and the network message go out after the map is populated
        m->show();
        timer->start(timeout * 1000);

        sendNetworkMessage("STATION.AUTOREPLY_CONFIRM_REQUEST", message,
            {{"_ID", QVariant(-1)},
             {"CONFIRM_ID", QVariant(id)},
             {"PRIORITY", QVariant(priority)},
             {"OFFSET", QVariant(offset)},
             {"TIMEOUT", QVariant(timeout)}});
    });
}
