/*
 * lg_settlerecon_batch.pgc - lg 원장-정산 대사 배치 (커서 + XA).
 *
 * 당일 정산(settlement) 순액과 원장 MERCH_PAY 대변 합계를 가맹점별로 FULL
 * JOIN 비교해 일치/불일치를 판정한다. 전 가맹점 일치 시 당일 SETTLE 전표를
 * M(대사)으로 일괄 승격. 모두 ONE global XA transaction 에서 수행.
 * Usage: lg_settlerecon_batch [YYYY-MM-DD]
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <atmi.h>
#include "lg_dbio.h"
#include "lg_settlerecon_batch.h"

int main(int argc, char **argv)
{
    lg_settlerecon_rec_t rec;
    long gap;

    EXEC SQL BEGIN DECLARE SECTION;
    char h_bizdate[16], h_merch[64];
    long h_setnet, h_ledcr, h_marked;
    EXEC SQL END DECLARE SECTION;

    memset(&rec, 0, sizeof(rec));
    strncpy(rec.biz_date, (argc > 1) ? argv[1] : "2026-07-19", sizeof(rec.biz_date)-1);
    strncpy(h_bizdate, rec.biz_date, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;

    if (tpinit(NULL) < 0) { fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno)); return 1; }
    if (tpopen() < 0)     { fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno)); return 1; }
    if (tpbegin(60, 0) < 0) { fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno)); return 1; }

    EXEC SQL DECLARE sr_cur CURSOR FOR
        SELECT coalesce(s.mid, l.mid),
               coalesce(s.net, 0), coalesce(l.cr, 0)
        FROM (SELECT merchant_id AS mid, sum(net) AS net
              FROM settlement WHERE biz_date = :h_bizdate GROUP BY merchant_id) s
        FULL JOIN (SELECT merchant_id AS mid, sum(amount) AS cr
                   FROM lg_ledger_line
                   WHERE biz_date = :h_bizdate AND acct = 'MERCH_PAY' AND dc = 'C'
                     AND merchant_id <> ''
                   GROUP BY merchant_id) l ON l.mid = s.mid
        ORDER BY 1;
    EXEC SQL OPEN sr_cur;
    if (sqlca.sqlcode < 0) { fprintf(stderr, "OPEN FAIL [%d] %s\n", sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc); tpabort(0); return 1; }

    for (;;) {
        EXEC SQL FETCH sr_cur INTO :h_merch, :h_setnet, :h_ledcr;
        if (sqlca.sqlcode == 100) break;
        if (sqlca.sqlcode < 0) { fprintf(stderr, "FETCH FAIL [%d]\n", sqlca.sqlcode); EXEC SQL CLOSE sr_cur; tpabort(0); return 1; }
        gap = h_setnet - h_ledcr;
        if (gap == 0) rec.matched++;
        else {
            printf("    불일치: %s 정산 %ld vs 원장 %ld (갭 %ld)\n", h_merch, h_setnet, h_ledcr, gap);
            rec.gap_total += (gap > 0) ? gap : -gap;
            rec.mismatched++;
        }
    }
    EXEC SQL CLOSE sr_cur;

    h_marked = 0;
    if (rec.mismatched == 0 && rec.matched > 0) {
        EXEC SQL UPDATE lg_voucher SET status = 'M', updated_at = now()
            WHERE voucher_type = 'SETTLE' AND biz_date = :h_bizdate AND status = 'P';
        if (sqlca.sqlcode < 0) { fprintf(stderr, "MARK FAIL [%d]\n", sqlca.sqlcode); tpabort(0); return 1; }
        h_marked = sqlca.sqlerrd[2];
    }

    if (tpcommit(0) < 0) { fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno)); tpabort(0); return 1; }
    printf(">>> lg_settlerecon_batch COMMIT: %s 일치 %ld / 불일치 %ld (절대갭 %ld) %ld전표 대사\n",
           rec.biz_date, rec.matched, rec.mismatched, rec.gap_total, h_marked);

    tpclose(); tpterm();
    return 0;
}
