/*
 * ST_ISSUERSTAT.pgc - st (정산/수수료) 모듈 서비스 ST_ISSUERSTAT (one service = one file).
 * 발급사별 수수료 분해 통계. (심화판).
 * 심화 온라인 프로그램: 입력검증 -> 마스터/정책 조회 -> 업무규칙 분기 -> 본처리 ->
 * 이력적재 -> 집계 재계산 -> 예외보상 -> 응답 -> 로깅. 호출자의 XA 브랜치에서 수행하며
 * EXEC SQL CONNECT 는 두지 않는다. 진입 서명/서비스명/입출력 계약은 불변.
 */
#include "ST_ISSUERSTAT.h"

/* ST_ISSUERSTAT - 발급사별 수수료 분해 통계. (심화판). (심화판) */
void ST_ISSUERSTAT(TPSVCINFO *p)
{
    UBFH *b = (UBFH *)p->data;
    /* ---- 지역 스크래치 (DECLARE SECTION 밖에서 초기화) ---- */
    char merch[64], bizdate[16], paydate[16], reason[128], ftype[16];
    char msgbuf[200], ym[16], chan[16];
    long amount, net0, fee0, delta0, tmp;
    int  vstep = 0;

    EXEC SQL BEGIN DECLARE SECTION;
    long h_pid, h_sid, h_amount, h_fee, h_net, h_bps, h_mdr, h_limit;
    long h_cnt, h_sum, h_gmax, h_gmin, h_avg, h_rows, h_id, h_prior;
    long h_delta, h_gross, h_feesum, h_netsum, h_tax, h_days, h_base, h_supply, h_n;
    char h_merch[64], h_bizdate[16], h_paydate[16], h_status[16], h_ftype[16];
    char h_reason[128], h_msg[200], h_svc[24], h_mstatus[16], h_ym[16], h_like[24];
    EXEC SQL END DECLARE SECTION;

    strcpy(h_svc, "ST_ISSUERSTAT");
    h_fee = 0; h_delta = 0; h_id = 0; h_cnt = 0; h_netsum = 0; h_base = 0;
    h_days = 0; h_supply = 0; h_tax = 0; h_gross = 0; h_prior = 0; h_n = 0;
    h_amount = 0; h_net = 0; h_sum = 0; h_gmax = 0; h_gmin = 0; h_avg = 0; h_rows = 0;
    h_feesum = 0;

    /* ===== 1) 입력 검증부 ===== */
    gets_(b, T_MERCHANT, merch, sizeof(merch));
    gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
    gets_(b, T_REASON, reason, sizeof(reason));
    gets_(b, T_STR1, ftype, sizeof(ftype));
    amount = getl(b, T_AMOUNT); net0 = getl(b, T_NET); fee0 = getl(b, T_FEE);
    delta0 = getl(b, T_DELTA); h_pid = getl(b, T_PURCHASE_ID); h_sid = getl(b, T_SETTLE_ID);
    if (bizdate[0] == 0) strcpy(bizdate, "2026-07-20");
    if (ftype[0] == 0)  strcpy(ftype, "MDR");
    if (reason[0] == 0) strcpy(reason, "ST_ISSUERSTAT");
    userlog("[정산심화] 발급사별 수수료 분해 통계. (심화판) 진입 pid=%ld merch=%s biz=%s", h_pid, merch, bizdate);
    if (amount < 0) { setl(b, T_RC, 11); Bchg(b, T_MSG, 0, "매입 금액은 음수가 될 수 없습니다", 0L); FAIL(b); }
    if (fee0 < 0)   { setl(b, T_RC, 12); Bchg(b, T_MSG, 0, "수수료 입력값이 음수입니다", 0L); FAIL(b); }
    if (strlen(bizdate) < 8) { setl(b, T_RC, 13); Bchg(b, T_MSG, 0, "영업일 형식 오류(YYYY-MM-DD)", 0L); FAIL(b); }
    if (net0 < 0 && fee0 == 0) { setl(b, T_RC, 16); Bchg(b, T_MSG, 0, "정산 금액(net) 음수 입력 불가", 0L); FAIL(b); }
    if (h_sid < 0) { setl(b, T_RC, 17); Bchg(b, T_MSG, 0, "정산 ID(settlement_id) 음수 오류", 0L); FAIL(b); }
    if (delta0 > 100000000 || delta0 < -100000000) { setl(b, T_RC, 18); Bchg(b, T_MSG, 0, "조정 금액 허용범위(±1억) 초과", 0L); FAIL(b); }
    strncpy(h_merch, merch, sizeof(h_merch)-1); h_merch[sizeof(h_merch)-1] = 0;
    strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
    strncpy(h_ftype, ftype, sizeof(h_ftype)-1); h_ftype[sizeof(h_ftype)-1] = 0;
    strncpy(h_reason, reason, sizeof(h_reason)-1); h_reason[sizeof(h_reason)-1] = 0;
    vstep = 1;

    /* ===== 2) 마스터/정책/상태 조회부 ===== */
    h_mdr = 25; h_limit = 0; strcpy(h_mstatus, "ACTIVE");
    if (merch[0] != 0) {
        EXEC SQL SELECT mdr_bps, daily_limit, status
            INTO :h_mdr, :h_limit, :h_mstatus FROM merchant WHERE merchant_id = :h_merch;
        if (sqlca.sqlcode == 100) { setl(b, T_RC, 21); Bchg(b, T_MSG, 0, "미등록 가맹점입니다", 0L); FAIL(b); }
        if (sqlca.sqlcode < 0)   { setl(b, T_RC, 22); Bchg(b, T_MSG, 0, "가맹점 마스터 조회 오류", 0L); FAIL(b); }
    }
    h_bps = getl(b, T_ARG2); if (h_bps <= 0) h_bps = h_mdr;   /* 계약 요율 우선, 없으면 가맹점 MDR */
    vstep = 2;

    /* ===== 2b) 한도/직전 지급잔량 조회부 ===== */
    h_sum = 0; h_avg = 0; h_n = 0; h_gross = 0;
    if (merch[0] != 0) {
        EXEC SQL SELECT coalesce(sum(amount),0) INTO :h_sum FROM purchase
            WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
        if (sqlca.sqlcode < 0) { setl(b, T_RC, 26); Bchg(b, T_MSG, 0, "당일 매입 누계 조회 오류", 0L); FAIL(b); }
        h_avg = h_limit - h_sum;   /* 일 한도 잔여 */
        if (h_limit > 0 && h_sum > h_limit)
            userlog("[정산심화] 발급사별 수수료 분해 통계. (심화판) 일 한도 초과 감지 sum=%ld limit=%ld", h_sum, h_limit);
    }
    EXEC SQL SELECT count(*), coalesce(sum(net_amount),0) INTO :h_n, :h_gross
        FROM st_payment WHERE merchant_id = :h_merch AND status = 'SCHEDULED';
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 27); Bchg(b, T_MSG, 0, "예정 지급 잔량 조회 오류", 0L); FAIL(b); }
    setl(b, T_ARG6, h_avg);
    vstep = 3;

    /* ===== 3) 업무규칙 분기부 ===== */
    if (amount >= 10000000) { h_prior = 3; userlog("[정산심화] %s 대액 구간(>=1천만) 처리", "발급사별 수수료 분해 통계. (심화판)"); }
    else if (amount >= 1000000) { h_prior = 2; userlog("[정산심화] %s 중액 구간 처리", "발급사별 수수료 분해 통계. (심화판)"); }
    else { h_prior = 1; userlog("[정산심화] %s 소액 구간 처리", "발급사별 수수료 분해 통계. (심화판)"); }
    gets_(b, T_CHANNEL, chan, sizeof(chan)); if (chan[0] == 0) strcpy(chan, "POS");
    if (strcmp(chan, "FOREIGN") == 0) { h_prior += 10; userlog("[정산심화] %s 해외 채널 가산 분기", "발급사별 수수료 분해 통계. (심화판)"); }
    else if (strcmp(chan, "EDI") == 0) { h_prior += 5; userlog("[정산심화] %s EDI 채널 분기", "발급사별 수수료 분해 통계. (심화판)"); }
    else { userlog("[정산심화] %s 국내 채널 표준 분기", "발급사별 수수료 분해 통계. (심화판)"); }
    if (h_mdr >= 30) userlog("[정산심화] 발급사별 수수료 분해 통계. (심화판) 고율 등급 가맹점(bps=%ld)", h_mdr);
    else if (h_mdr <= 20) userlog("[정산심화] 발급사별 수수료 분해 통계. (심화판) 우대 등급 가맹점(bps=%ld)", h_mdr);
    vstep = 3;

    /* ===== 4) 본처리부 ===== */
    EXEC SQL SELECT count(*), coalesce(sum(amount),0), coalesce(max(amount),0), coalesce(min(amount),0)
        INTO :h_cnt, :h_feesum, :h_gmax, :h_gmin
        FROM st_settle_dtl WHERE biz_date = :h_bizdate AND fee_type = :h_ftype;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 55); Bchg(b, T_MSG, 0, "수수료 상세 집계 오류", 0L); FAIL(b); }
    h_avg = h_cnt > 0 ? h_feesum / h_cnt : 0; h_netsum = h_feesum;
    setl(b, T_AMT1, h_gmax); setl(b, T_AMT2, h_gmin); setl(b, T_AMT3, h_avg);
    setl(b, T_COUNT, h_cnt); setl(b, T_GROSS, h_netsum);
    userlog("[정산심화] 발급사별 수수료 분해 통계. (심화판) cnt=%ld sum=%ld", h_cnt, h_netsum);
    vstep = 4;

    /* ===== 5) 이력/감사 적재부 (cm_log) ===== */
    snprintf(msgbuf, sizeof(msgbuf), "발급사별 수수료 분해 통계. (심화판) [ST_ISSUERSTAT] pid=%ld fee=%ld delta=%ld net=%ld", h_pid, h_fee, h_delta, h_netsum);
    strncpy(h_msg, msgbuf, sizeof(h_msg)-1); h_msg[sizeof(h_msg)-1] = 0;
    EXEC SQL INSERT INTO cm_log (log_id, svc_name, log_level, msg, biz_date)
        VALUES (nextval('cm_log_seq'), :h_svc, 'I', :h_msg, :h_bizdate);
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 91); Bchg(b, T_MSG, 0, "감사 로그 적재 실패", 0L); FAIL(b); }
    vstep = 5;

    /* ===== 6) 집계/요약 갱신부 ===== */
    EXEC SQL SELECT count(*) INTO :h_rows FROM settlement WHERE biz_date = :h_bizdate;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 65); Bchg(b, T_MSG, 0, "일 정산 건수 재확인 오류", 0L); FAIL(b); }
    setl(b, T_ARG3, h_rows);
    vstep = 6;

    /* ===== 7) 예외/보상 검증부 ===== */
    EXEC SQL SELECT count(*) INTO :h_rows FROM cm_log
        WHERE svc_name = :h_svc AND biz_date = :h_bizdate;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 71); Bchg(b, T_MSG, 0, "감사 로그 검증 조회 오류", 0L); FAIL(b); }
    if (h_rows <= 0) { setl(b, T_RC, 72); Bchg(b, T_MSG, 0, "감사 로그 미적재(보상 롤백)", 0L); FAIL(b); }
    setl(b, T_ARG5, h_rows);
    userlog("[정산심화] 발급사별 수수료 분해 통계. (심화판) 보상검증 통과 logrows=%ld step=%d", h_rows, vstep);
    vstep = 7;

    /* ===== 8) 응답부 ===== */
    if (Bpres(b, T_RC, 0) == 0) setl(b, T_RC, 0);
    Bchg(b, T_SVCNAME, 0, "ST_ISSUERSTAT", 0L);
    setl(b, T_ARG4, (long)vstep);
    /* ===== 9) 완료 로깅 ===== */
    userlog("[정산심화] 발급사별 수수료 분해 통계. (심화판) 완료 rc=0 pid=%ld fee=%ld net=%ld", h_pid, h_fee, h_netsum);
    OK(b);
}

/* vim: set ts=4 sw=4 et smartindent: */
