/*
 * cm_code_dbio.pgc - 공통코드/환율/휴일 DB 접근 (part of libcmdbio.a).
 * ECPG functions; run on the caller's XA branch. No EXEC SQL CONNECT.
 */
#include <string.h>
#include <userlog.h>
#include "cm_dbio.h"

int cmdb_get_code_name(const char *grp, const char *code, char *out)
{
    EXEC SQL BEGIN DECLARE SECTION;
    char h_grp[32], h_code[32], h_name[128];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_grp, grp, sizeof(h_grp)-1);   h_grp[sizeof(h_grp)-1] = 0;
    strncpy(h_code, code, sizeof(h_code)-1); h_code[sizeof(h_code)-1] = 0;

    EXEC SQL SELECT code_name INTO :h_name FROM cm_code
        WHERE code_grp = :h_grp AND code = :h_code AND use_yn = 'Y';
    if (sqlca.sqlcode == 100) { out[0] = 0; return -1; }
    if (sqlca.sqlcode < 0) {
        userlog("cmdb_get_code_name FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    /* 실제 값 길이만 복사 (strncpy 의 NUL 패딩으로 호출자 스택을 넘어 쓰는 것 방지).
     * 상세 사유는 cm_param_dbio.pgc 의 cmdb_get_param 주석 참조. */
    {
        size_t vn = strlen(h_name);
        if (vn > 127) vn = 127;
        memcpy(out, h_name, vn);
        out[vn] = 0;
    }
    return 0;
}

int cmdb_code_exists(const char *grp, const char *code)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_cnt;
    char h_grp[32], h_code[32];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_grp, grp, sizeof(h_grp)-1);   h_grp[sizeof(h_grp)-1] = 0;
    strncpy(h_code, code, sizeof(h_code)-1); h_code[sizeof(h_code)-1] = 0;

    EXEC SQL SELECT count(*) INTO :h_cnt FROM cm_code
        WHERE code_grp = :h_grp AND code = :h_code;
    if (sqlca.sqlcode < 0) {
        userlog("cmdb_code_exists FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return h_cnt > 0 ? 1 : 0;
}

int cmdb_insert_code(const char *grp, const char *code, const char *name, long sort)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_sort = sort;
    char h_grp[32], h_code[32], h_name[128];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_grp, grp, sizeof(h_grp)-1);   h_grp[sizeof(h_grp)-1] = 0;
    strncpy(h_code, code, sizeof(h_code)-1); h_code[sizeof(h_code)-1] = 0;
    strncpy(h_name, name, sizeof(h_name)-1); h_name[sizeof(h_name)-1] = 0;

    EXEC SQL INSERT INTO cm_code (code_grp, code, code_name, sort_ord)
        VALUES (:h_grp, :h_code, :h_name, :h_sort)
        ON CONFLICT (code_grp, code) DO UPDATE
        SET code_name = EXCLUDED.code_name, sort_ord = EXCLUDED.sort_ord, updated_at = now();
    if (sqlca.sqlcode < 0) {
        userlog("cmdb_insert_code FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return 0;
}

long cmdb_count_codes(const char *grp)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_cnt;
    char h_grp[32];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_grp, grp, sizeof(h_grp)-1); h_grp[sizeof(h_grp)-1] = 0;

    EXEC SQL SELECT count(*) INTO :h_cnt FROM cm_code
        WHERE code_grp = :h_grp AND use_yn = 'Y';
    if (sqlca.sqlcode < 0) {
        userlog("cmdb_count_codes FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return h_cnt;
}

int cmdb_get_fx_rate(const char *ccy, const char *base_date, long *rate_out)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_rate;
    char h_ccy[8], h_date[16];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_ccy, ccy, sizeof(h_ccy)-1);   h_ccy[sizeof(h_ccy)-1] = 0;
    strncpy(h_date, base_date, sizeof(h_date)-1); h_date[sizeof(h_date)-1] = 0;

    /* 요청일 이하 가장 최근 기준일 환율 */
    EXEC SQL SELECT rate_bps INTO :h_rate FROM cm_fx_rate
        WHERE ccy = :h_ccy AND base_date <= :h_date
        ORDER BY base_date DESC LIMIT 1;
    if (sqlca.sqlcode == 100) return -1;
    if (sqlca.sqlcode < 0) {
        userlog("cmdb_get_fx_rate FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    *rate_out = h_rate;
    return 0;
}

int cmdb_is_holiday(const char *date)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_cnt;
    char h_date[16];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_date, date, sizeof(h_date)-1); h_date[sizeof(h_date)-1] = 0;

    EXEC SQL SELECT count(*) INTO :h_cnt FROM cm_holiday WHERE holi_date = :h_date;
    if (sqlca.sqlcode < 0) {
        userlog("cmdb_is_holiday FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return h_cnt > 0 ? 1 : 0;
}
