/*
 * PAY_ADVCALC.pgc - py (지급) 모듈 온라인 서비스 PAY_ADVCALC.
 * 선지급 가능액 산정: 가맹점 미지급(R/A) 잔액에 지급률(bps)을 곱한 한도에서
 * 이미 나간 선지급(ADVANCE, 미상환) 잔액을 차감해 추가 가능액을 회신한다.
 * 처리 구성: 입력검증 -> 마스터/정책 조회 -> 업무규칙 분기 -> 본처리 ->
 *            감사이력 적재 -> 집계 갱신 -> 예외보상 -> 응답 -> 로깅 [calc].
 * Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by py_svr.
 */
#include "PAY_ADVCALC.h"

void PAY_ADVCALC(TPSVCINFO *p)
{
    UBFH *b = (UBFH *)p->data;
    EXEC SQL BEGIN DECLARE SECTION;
    long h_arg1;
    char h_merchant[64];
    long h_wcnt;
    long h_wsum;
    long h_wnet;
    long h_wlim;
    long h_wused;
    long h_waff;
    long h_wval;
    long h_wrate;
    char h_wst[8];
    char h_wmerch[64];
    char h_wacct[64];
    char h_wdate[16];
    char h_pval[32];
    long h_thr;
    char h_lvl[4];
    char h_amsg[256];
    long h_wz1;
    long h_wz2;
    long h_wz3;
    EXEC SQL END DECLARE SECTION;

    /* 1) 입력 검증부 - 모든 입력 필드의 필수/범위/형식 검사 */
    h_arg1 = getl(b, T_ARG1);
    if (h_arg1 < 0) h_arg1 = 0;
    gets_(b, T_MERCHANT, h_merchant, sizeof(h_merchant));
    if (h_merchant[0] == 0) {
        setl(b, T_RC, 12);
        Bchg(b, T_MSG, 0, "가맹점 ID는 필수 입력", 0L);
        FAIL(b);
    }
    EXEC SQL SELECT to_char(current_date, 'YYYY-MM-DD') INTO :h_wdate;
    if (sqlca.sqlcode < 0) strcpy(h_wdate, "1970-01-01");
    /* 2) 마스터 조회부 - 가맹점 상태/한도 및 미지급 잔액 */
    EXEC SQL SELECT status, daily_limit INTO :h_wst, :h_wlim
        FROM merchant WHERE merchant_id = :h_merchant;
    if (sqlca.sqlcode == 100) {
        setl(b, T_RC, 40);
        Bchg(b, T_MSG, 0, "가맹점 미등록", 0L);
        FAIL(b);
    }
    if (sqlca.sqlcode < 0) {
        setl(b, T_RC, 41);
        Bchg(b, T_MSG, 0, "가맹점 조회 오류", 0L);
        FAIL(b);
    }
    EXEC SQL SELECT count(*), coalesce(sum(net),0) INTO :h_wcnt, :h_wsum
        FROM py_payout WHERE merchant_id = :h_merchant AND status IN ('R','A');
    if (sqlca.sqlcode < 0) { h_wcnt = 0; h_wsum = 0; }
    /* 기 실행된 선지급 잔액 */
    EXEC SQL SELECT coalesce(sum(net),0) INTO :h_wused FROM py_payout
        WHERE merchant_id = :h_merchant AND channel = 'ADVANCE'
          AND status IN ('A','F','P');
    if (sqlca.sqlcode < 0) h_wused = 0;
    strcpy(h_pval, "7000");
    EXEC SQL SELECT coalesce(param_val, :h_pval) INTO :h_pval
        FROM cm_param WHERE param_key = 'pay_adv_default_bps';
    if (sqlca.sqlcode < 0) {
        setl(b, T_RC, 91);
        Bchg(b, T_MSG, 0, "정책 파라미터(cm_param) 조회 실패", 0L);
        FAIL(b);
    }
    h_thr = atol(h_pval);
    if (h_thr <= 0) h_thr = 7000;
    /* 3) 업무규칙 분기부 - 지급률 구간별 선지급 가능액 (3분기) */
    if (strcmp(h_wst, "ACTIVE") != 0) {
        setl(b, T_RC, 42);
        Bchg(b, T_MSG, 0, "비활성 가맹점은 선지급 산정 불가", 0L);
        FAIL(b);
    }
    if (h_arg1 == 0) {
        h_wrate = h_thr;
    } else if (h_arg1 > 10000) {
        h_wrate = 10000;
    } else {
        h_wrate = h_arg1;
    }
    h_wval = h_wsum * h_wrate / 10000;
    h_waff = h_wval - h_wused;
    if (h_waff < 0) h_waff = 0;
    if (h_wlim > 0 && h_waff > h_wlim) h_waff = h_wlim;
    strcpy(h_lvl, "I");
    snprintf(h_amsg, sizeof(h_amsg), "%s merch=%s 미지급=%ld 가능액=%ld 기실행=%ld", "PAY_ADVCALC", h_merchant, h_wsum, h_waff, h_wused);
    EXEC SQL INSERT INTO cm_log (log_id, svc_name, log_level, msg, biz_date)
        VALUES (nextval('cm_log_seq'), 'PAY_ADVCALC', :h_lvl, :h_amsg, :h_wdate);
    if (sqlca.sqlcode < 0) {
        setl(b, T_RC, 92);
        Bchg(b, T_MSG, 0, "감사로그(cm_log) 적재 실패 - 처리 롤백", 0L);
        FAIL(b);
    }
    /* 8) 응답부 */
    if (h_wcnt == 0) {
        setl(b, T_RC, 1); Bchg(b, T_MSG, 0, "선지급 대상 미지급건 없음", 0L);
    } else if (h_waff == 0) {
        setl(b, T_RC, 2); Bchg(b, T_MSG, 0, "선지급 가용 한도 소진", 0L);
    } else {
        setl(b, T_RC, 0); Bchg(b, T_MSG, 0, "선지급 가능", 0L);
    }
    setl(b, T_AMT1, h_wval);
    setl(b, T_AMT2, h_wused);
    setl(b, T_ARG1, h_wrate);
    setl(b, T_GROSS, h_waff);
    userlog("PAY_ADVCALC 완료: merch=%s 가능액=%ld", h_merchant, h_waff);
    /* 7) 예외/보상 점검부 - 당일 지급 원장 사후 정합 확인 */
    EXEC SQL SELECT count(*), coalesce(sum(net),0) INTO :h_wz1, :h_wz2
        FROM py_payout WHERE biz_date = :h_wdate;
    if (sqlca.sqlcode < 0) { h_wz1 = 0; h_wz2 = 0; }
    EXEC SQL SELECT count(*) INTO :h_wz3 FROM py_payout
        WHERE biz_date = :h_wdate AND amount - fee <> net;
    if (sqlca.sqlcode < 0) h_wz3 = 0;
    if (h_wz3 > 0) {
        userlog("%s 순액 정합 위반 감지: %ld건 / 당일 %ld건",
                "PAY_ADVCALC", h_wz3, h_wz1);
    }
    if (h_wz2 < 0) {
        setl(b, T_RC, 93);
        Bchg(b, T_MSG, 0, "당일 지급 순액 합계가 음수 - 원장 정합 오류", 0L);
        FAIL(b);
    }
    OK(b);
}
