/* @tier medium @module mg @transform msg-gateway-online */
/*
 * mg_ol_0020.pgc - 전문게이트웨이 전문 순번(STAN) 채번 서비스 (MG_OL_0020)  [tier=medium]
 *
 * 채널/기관 단위 시퀀스행(mg_seq)을 원자적으로 증가시켜 6자리 STAN
 * (System Trace Audit Number)을 채번한다. raw EXEC SQL 로 UPDATE ...
 * SET seq_val = seq_val + 1 후 증가값을 SELECT 하며, 000001~999999 를
 * 순환(랩어라운드)한다. 시퀀스행이 없으면 최초 1 로 생성한다.
 */
#include <stdio.h>
#include <string.h>

#include "txcore.h"
#include "txcore_dbio.h"
#include "acq_util.h"
#include "mg_core.h"

EXEC SQL INCLUDE sqlca;

#define STAN_MAX 999999

TX_SERVICE(MG_OL_0020, ctx)
{
    EXEC SQL BEGIN DECLARE SECTION;
    char h_seqname[16];
    long h_seqval;
    long h_stanmax;
    EXEC SQL END DECLARE SECTION;

    char seqname[16];
    char stan[8];
    long stanval;

    tx_log(TX_LOG_INFO, "[MG_OL_0020] STAN 채번 서비스 진입");

    if (tx_buf_get(ctx->in, "SEQNAME", seqname, sizeof(seqname)) != TX_OK ||
        seqname[0] == '\0') {
        tx_log(TX_LOG_ERROR, "[MG_OL_0020] 시퀀스명(SEQNAME) 누락");
        tx_return(ctx, TX_EINVAL, ctx->out);
        return;
    }
    strncpy(h_seqname, seqname, sizeof(h_seqname) - 1);
    h_seqname[sizeof(h_seqname) - 1] = '\0';
    h_stanmax = STAN_MAX;

    if (tx_begin() != TX_OK) {
        tx_return(ctx, TX_FAIL, ctx->out);
        return;
    }

    /* 원자적 증가 (랩어라운드는 갱신식 내에서 처리) */
    EXEC SQL UPDATE mg_seq
        SET seq_val = (CASE WHEN seq_val >= :h_stanmax THEN 1
                            ELSE seq_val + 1 END),
            upd_ts = now()
        WHERE seq_name = :h_seqname;
    if (sqlca.sqlcode != TX_SQL_OK) {
        TX_DBIO_LOG_ERR("MG_OL_0020 mg_seq update");
        tx_abort();
        tx_return(ctx, TX_EDB, ctx->out);
        return;
    }

    /* 대상행이 없으면 최초 1 로 생성 */
    if (sqlca.sqlerrd[2] == 0) {
        h_seqval = 1;
        EXEC SQL INSERT INTO mg_seq (seq_name, seq_val, upd_ts)
            VALUES (:h_seqname, :h_seqval, now());
        if (sqlca.sqlcode != TX_SQL_OK) {
            TX_DBIO_LOG_ERR("MG_OL_0020 mg_seq insert");
            tx_abort();
            tx_return(ctx, TX_EDB, ctx->out);
            return;
        }
        tx_log(TX_LOG_INFO, "[MG_OL_0020] 시퀀스 신규생성 name=%s", seqname);
    }

    /* 증가 결과 조회 */
    EXEC SQL SELECT seq_val
        INTO :h_seqval
        FROM mg_seq
        WHERE seq_name = :h_seqname;
    if (sqlca.sqlcode != TX_SQL_OK) {
        TX_DBIO_LOG_ERR("MG_OL_0020 mg_seq select");
        tx_abort();
        tx_return(ctx, TX_EDB, ctx->out);
        return;
    }

    tx_commit();

    stanval = h_seqval;
    if (stanval < 1 || stanval > STAN_MAX)
        stanval = ((stanval - 1) % STAN_MAX) + 1;
    snprintf(stan, sizeof(stan), "%06ld", stanval);

    tx_buf_reset(ctx->out);
    tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
    tx_buf_sets(ctx->out, "SEQNAME", seqname);
    tx_buf_sets(ctx->out, "STAN", stan);
    tx_buf_setlong(ctx->out, "SEQVAL", stanval);
    tx_log(TX_LOG_INFO, "[MG_OL_0020] STAN 채번완료 name=%s stan=%s", seqname, stan);
    tx_return(ctx, TX_OK, ctx->out);
}
