/* @tier medium @module st @transform settlement-online */
/*
 * st_ol_0031.pgc - 정산 확정 처리 (ST_OL_0031)  [tier=medium]
 *
 * 처리완료(M) 건을 정산완료(S)로 확정 전이한다. 완료 상태가 아닌 건은
 * 확정 불가로 반려한다. 상태 전이는 원장(st_ledger)에 M->S 조건부
 * 임베디드 UPDATE 로 반영한다.
 */
#include <stdio.h>
#include <string.h>

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

EXEC SQL INCLUDE sqlca;


TX_SERVICE(ST_OL_0031, ctx)
{
    EXEC SQL BEGIN DECLARE SECTION;
    char h_key[16];
    char h_status[2];
    long h_amount;
    long h_fee;
    long h_affected;
    EXEC SQL END DECLARE SECTION;

    char key[16];

    tx_log(TX_LOG_INFO, "[ST_OL_0031] 정산 확정 처리 진입");

    if (tx_buf_get(ctx->in, "KEY", key, sizeof(key)) != TX_OK) {
        tx_return(ctx, TX_EINVAL, ctx->out);
        return;
    }

    /* 현재 상태/금액 조회 */
    strncpy(h_key, key, sizeof(h_key) - 1);
    h_key[sizeof(h_key) - 1] = '\0';
    memset(h_status, 0, sizeof(h_status));
    h_amount = 0;
    h_fee    = 0;
    EXEC SQL SELECT status, amount, fee
        INTO :h_status, :h_amount, :h_fee
        FROM st_ledger
        WHERE key = :h_key;

    if (sqlca.sqlcode == TX_SQL_NOTFOUND) {
        tx_return(ctx, TX_ENOENT, ctx->out);
        return;
    }
    if (sqlca.sqlcode != TX_SQL_OK) {
        TX_DBIO_LOG_ERR("SELECT st_ledger 확정");
        tx_return(ctx, TX_EDB, ctx->out);
        return;
    }

    if (memcmp(h_status, ST_ST_DONE, 1) != 0) {
        tx_log(TX_LOG_WARN, "[ST_OL_0031] 확정 불가 상태 key=%s st=%s", key, h_status);
        tx_buf_reset(ctx->out);
        tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
        tx_buf_sets(ctx->out, "REASON", "NOT_DONE");
        tx_return(ctx, TX_FAIL, ctx->out);
        return;
    }

    /* M -> S 조건부 확정 전이 */
    if (tx_begin() != TX_OK)
        tx_log(TX_LOG_WARN, "[ST_OL_0031] tx_begin 경고");

    EXEC SQL UPDATE st_ledger
        SET status = 'S', upd_ts = now()
        WHERE key = :h_key
          AND status = 'M';

    if (sqlca.sqlcode != TX_SQL_OK) {
        TX_DBIO_LOG_ERR("UPDATE st_ledger 확정");
        tx_abort();
        tx_return(ctx, TX_EDB, ctx->out);
        return;
    }
    h_affected = sqlca.sqlerrd[2];
    if (h_affected == 0) {
        tx_abort();
        tx_log(TX_LOG_WARN, "[ST_OL_0031] 확정 반영 0건 key=%s", key);
        tx_buf_reset(ctx->out);
        tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID);
        tx_return(ctx, TX_FAIL, ctx->out);
        return;
    }
    tx_commit();

    tx_buf_reset(ctx->out);
    tx_buf_sets(ctx->out, "RESPCODE", RESP_OK);
    tx_buf_sets(ctx->out, "KEY", key);
    tx_buf_sets(ctx->out, "STATUS", ST_ST_SETTLED);
    tx_buf_setlong(ctx->out, "NET", h_amount - h_fee);
    tx_log(TX_LOG_INFO, "[ST_OL_0031] 정산확정 key=%s net=%ld", key, h_amount - h_fee);
    tx_return(ctx, TX_OK, ctx->out);
}
