/*
 * mg_msg_dbio.pgc - 전문 로그/채번/큐 DB 접근 (part of libmgdbio.a).
 * ECPG functions; run on the caller's XA branch. No EXEC SQL CONNECT.
 */
#include <string.h>
#include <userlog.h>
#include "mg_dbio.h"

long mgdb_next_stan(void)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_id;
    EXEC SQL END DECLARE SECTION;

    EXEC SQL SELECT nextval('mg_stan_seq') INTO :h_id;
    if (sqlca.sqlcode < 0) {
        userlog("mgdb_next_stan FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return h_id;
}

long mgdb_next_msg_id(void)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_id;
    EXEC SQL END DECLARE SECTION;

    EXEC SQL SELECT nextval('mg_msg_seq') INTO :h_id;
    if (sqlca.sqlcode < 0) {
        userlog("mgdb_next_msg_id FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return h_id;
}

long mgdb_next_queue_id(void)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_id;
    EXEC SQL END DECLARE SECTION;

    EXEC SQL SELECT nextval('mg_queue_seq') INTO :h_id;
    if (sqlca.sqlcode < 0) {
        userlog("mgdb_next_queue_id FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return h_id;
}

/* mg_seq 이름있는 카운터를 원자적으로 +1 하고 새 값을 돌려준다 (세션 시퀀스 채번). */
long mgdb_seq_bump(const char *name)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_val;
    char h_name[32];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_name, name, sizeof(h_name) - 1); h_name[sizeof(h_name)-1] = 0;

    EXEC SQL UPDATE mg_seq SET seq_val = seq_val + 1, updated_at = now()
        WHERE seq_name = :h_name;
    if (sqlca.sqlcode < 0) {
        userlog("mgdb_seq_bump UPDATE FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    if (sqlca.sqlcode == 100) {   /* 최초 사용: 행 생성 */
        EXEC SQL INSERT INTO mg_seq (seq_name, seq_val) VALUES (:h_name, 1);
        if (sqlca.sqlcode < 0) return -1;
        return 1;
    }
    EXEC SQL SELECT seq_val INTO :h_val FROM mg_seq WHERE seq_name = :h_name;
    if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) return -1;
    return h_val;
}

int mgdb_insert_msg(long msg_id, long stan, const char *mti, const char *channel,
                    const char *direction, const char *proc_code, const char *bitmap,
                    long amount, const char *pan, const char *rc, const char *raw,
                    const char *status, const char *bizdate)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_id = msg_id, h_stan = stan, h_amount = amount;
    char h_mti[8], h_chan[16], h_dir[8], h_proc[8], h_bitmap[40];
    char h_pan[24], h_rc[4], h_raw[512], h_status[4], h_bizdate[16];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_mti, mti, sizeof(h_mti)-1);          h_mti[sizeof(h_mti)-1] = 0;
    strncpy(h_chan, channel, sizeof(h_chan)-1);    h_chan[sizeof(h_chan)-1] = 0;
    strncpy(h_dir, direction, sizeof(h_dir)-1);    h_dir[sizeof(h_dir)-1] = 0;
    strncpy(h_proc, proc_code, sizeof(h_proc)-1);  h_proc[sizeof(h_proc)-1] = 0;
    strncpy(h_bitmap, bitmap, sizeof(h_bitmap)-1); h_bitmap[sizeof(h_bitmap)-1] = 0;
    strncpy(h_pan, pan, sizeof(h_pan)-1);          h_pan[sizeof(h_pan)-1] = 0;
    strncpy(h_rc, rc, sizeof(h_rc)-1);             h_rc[sizeof(h_rc)-1] = 0;
    strncpy(h_raw, raw, sizeof(h_raw)-1);          h_raw[sizeof(h_raw)-1] = 0;
    strncpy(h_status, status, sizeof(h_status)-1); h_status[sizeof(h_status)-1] = 0;
    strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;

    EXEC SQL INSERT INTO mg_msg_log
        (msg_id, stan, mti, channel, direction, proc_code, bitmap, amount,
         pan, rc, raw_msg, status, biz_date)
        VALUES (:h_id, :h_stan, :h_mti, :h_chan, :h_dir, :h_proc, :h_bitmap,
                :h_amount, :h_pan, :h_rc, :h_raw, :h_status, :h_bizdate);
    if (sqlca.sqlcode < 0) {
        userlog("mgdb_insert_msg FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return 0;
}

int mgdb_update_msg_rc(long msg_id, const char *rc, const char *status)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_id = msg_id;
    char h_rc[4], h_status[4];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_rc, rc, sizeof(h_rc)-1);             h_rc[sizeof(h_rc)-1] = 0;
    strncpy(h_status, status, sizeof(h_status)-1); h_status[sizeof(h_status)-1] = 0;

    EXEC SQL UPDATE mg_msg_log SET rc = :h_rc, status = :h_status WHERE msg_id = :h_id;
    if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) {
        userlog("mgdb_update_msg_rc FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return 0;
}

int mgdb_get_msg_status(long msg_id, char *out)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_id = msg_id;
    char h_status[4];
    EXEC SQL END DECLARE SECTION;

    EXEC SQL SELECT status INTO :h_status FROM mg_msg_log WHERE msg_id = :h_id;
    if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) {
        userlog("mgdb_get_msg_status FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    out[0] = h_status[0];
    out[1] = 0;
    return 0;
}

long mgdb_find_msg_by_stan(long stan)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_stan = stan, h_id;
    EXEC SQL END DECLARE SECTION;

    EXEC SQL SELECT msg_id INTO :h_id FROM mg_msg_log
        WHERE stan = :h_stan ORDER BY msg_id DESC LIMIT 1;
    if (sqlca.sqlcode == 100) return -1;
    if (sqlca.sqlcode < 0) {
        userlog("mgdb_find_msg_by_stan FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return h_id;
}

int mgdb_enqueue(long queue_id, long stan, const char *channel, const char *mti,
                 const char *payload, const char *bizdate)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_id = queue_id, h_stan = stan;
    char h_chan[16], h_mti[8], h_payload[512], h_bizdate[16];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_chan, channel, sizeof(h_chan)-1);       h_chan[sizeof(h_chan)-1] = 0;
    strncpy(h_mti, mti, sizeof(h_mti)-1);             h_mti[sizeof(h_mti)-1] = 0;
    strncpy(h_payload, payload, sizeof(h_payload)-1); h_payload[sizeof(h_payload)-1] = 0;
    strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;

    EXEC SQL INSERT INTO mg_queue (queue_id, stan, channel, mti, payload, status, biz_date)
        VALUES (:h_id, :h_stan, :h_chan, :h_mti, :h_payload, 'Q', :h_bizdate);
    if (sqlca.sqlcode < 0) {
        userlog("mgdb_enqueue FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return 0;
}

int mgdb_set_queue_status(long queue_id, const char *status)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_id = queue_id;
    char h_status[4];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_status, status, sizeof(h_status)-1); h_status[sizeof(h_status)-1] = 0;

    EXEC SQL UPDATE mg_queue SET status = :h_status, updated_at = now()
        WHERE queue_id = :h_id;
    if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) {
        userlog("mgdb_set_queue_status FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return 0;
}
