/*
 * ac_purchase_dbio.pgc - purchase/approval/ledger DB access (part of libacdbio.a).
 * ECPG functions; run on the caller's XA branch. No EXEC SQL CONNECT.
 */
#include <string.h>
#include <userlog.h>
#include "ac_dbio.h"

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

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

int acdb_insert_purchase(long pid, const char *merch, long amount, long fee,
                         long net, const char *status, const char *channel,
                         const char *bizdate)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_pid = pid, h_amount = amount, h_fee = fee, h_net = net;
    char h_merch[64], h_status[8], h_channel[16], h_bizdate[16];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_merch, merch, sizeof(h_merch) - 1);       h_merch[sizeof(h_merch)-1] = 0;
    strncpy(h_status, status, sizeof(h_status) - 1);    h_status[sizeof(h_status)-1] = 0;
    strncpy(h_channel, channel, sizeof(h_channel) - 1); h_channel[sizeof(h_channel)-1] = 0;
    strncpy(h_bizdate, bizdate, sizeof(h_bizdate) - 1); h_bizdate[sizeof(h_bizdate)-1] = 0;

    EXEC SQL INSERT INTO purchase
        (purchase_id, merchant_id, amount, fee, net, status, biz_date, channel)
        VALUES (:h_pid, :h_merch, :h_amount, :h_fee, :h_net, :h_status, :h_bizdate, :h_channel);
    if (sqlca.sqlcode < 0) {
        userlog("acdb_insert_purchase FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return 0;
}

int acdb_insert_approval(long pid, int approved)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_pid = pid;
    int  h_ok = approved;
    EXEC SQL END DECLARE SECTION;

    EXEC SQL INSERT INTO approval (approval_id, purchase_id, approved)
        VALUES (nextval('approval_seq'), :h_pid, :h_ok);
    if (sqlca.sqlcode < 0) {
        userlog("acdb_insert_approval FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return 0;
}

int acdb_update_status(long pid, const char *status)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_pid = pid;
    char h_status[8];
    EXEC SQL END DECLARE SECTION;

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

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

int acdb_get_status(long pid, char *out)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_pid = pid;
    char h_status[8];
    EXEC SQL END DECLARE SECTION;

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

int acdb_update_amount(long pid, long amount, long fee, long net)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_pid = pid, h_amount = amount, h_fee = fee, h_net = net;
    EXEC SQL END DECLARE SECTION;

    EXEC SQL UPDATE purchase
        SET amount = :h_amount, fee = :h_fee, net = :h_net, updated_at = now()
        WHERE purchase_id = :h_pid;
    if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) {
        userlog("acdb_update_amount FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return 0;
}

long acdb_insert_ledger(long pid, const char *type, long amount, const char *bizdate)
{
    EXEC SQL BEGIN DECLARE SECTION;
    long h_pid = pid, h_amount = amount;
    char h_type[16], h_bizdate[16];
    EXEC SQL END DECLARE SECTION;

    strncpy(h_type, type, sizeof(h_type) - 1);       h_type[sizeof(h_type)-1] = 0;
    strncpy(h_bizdate, bizdate, sizeof(h_bizdate) - 1); h_bizdate[sizeof(h_bizdate)-1] = 0;

    EXEC SQL INSERT INTO ledger (ledger_id, purchase_id, entry_type, amount, biz_date)
        VALUES (nextval('ledger_seq'), :h_pid, :h_type, :h_amount, :h_bizdate);
    if (sqlca.sqlcode < 0) {
        userlog("acdb_insert_ledger FAIL [%d] %s", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        return -1;
    }
    return 0;
}
