/*
 * ST_FEEDECOMP.pgc - st (정산/수수료) 모듈 서비스 ST_FEEDECOMP (one service = one file).
 * 수수료 3층 분해(심화판): MDR = interchange(발급사) + scheme_fee(카드망) + markup(매입사).
 * 처리단계: 입력검증 -> 매입/카드종류 결정 -> interchange/scheme 요율조회 -> 업무규칙(3층 산출)
 *   -> st_fee_component UPSERT -> 감사이력 -> 재검증 -> 응답 -> 로깅.
 * 호출자 XA 브랜치에서 수행(EXEC SQL CONNECT 없음). st_svr 가 tpsvrinit 에서 광고.
 * XA 격리: 체인 신규매입(미커밋)은 이 브랜치에서 안 보이므로 sqlcode=100 을 정상흐름으로 보고
 *   요청 전문(UBF)값을 사용한다(owner-writes 규율, RECONCILE.pgc 참고). 100 을 FAIL 로 처리하지 않는다.
 */
#include "ST_FEEDECOMP.h"

/* ST_FEEDECOMP - 수수료 3층 분해 (interchange + scheme_fee + markup). */
void ST_FEEDECOMP(TPSVCINFO *p)
{
    UBFH *b = (UBFH *)p->data;
    /* ---- 지역 스크래치 (DECLARE SECTION 밖에서 초기화) ---- */
    char  channel[16], issuer[40], ctype[16], scheme[16], msgbuf[200];
    long  amount, feein, persist;

    EXEC SQL BEGIN DECLARE SECTION;
    long  h_pid, h_amount, h_fee, h_icbps, h_icfix, h_sfbps, h_sffix;
    long  h_ic, h_sf, h_markup, h_mdr, h_floor, h_cnt;
    char  h_ctype[16], h_scheme[16], h_channel[16], h_issuer[40];
    char  h_merch[64], h_status[16], h_bizdate[16], h_svc[24], h_msg[200];
    EXEC SQL END DECLARE SECTION;

    strcpy(h_svc, "ST_FEEDECOMP");
    h_amount = h_fee = h_ic = h_sf = h_markup = h_mdr = h_cnt = 0;
    h_icbps = 0; h_icfix = 0; h_sfbps = 0; h_sffix = 0; h_floor = 0;
    strcpy(h_channel, "POS"); strcpy(h_issuer, "UNKNOWN"); strcpy(h_merch, "-");
    strcpy(h_status, "S"); strcpy(h_bizdate, "2026-07-20");
    persist = 0;

    /* ===== 1) 입력 검증부 ===== */
    h_pid  = getl(b, T_PURCHASE_ID);
    amount = getl(b, T_AMOUNT);
    feein  = getl(b, T_FEE);
    gets_(b, T_CHANNEL, channel, sizeof(channel));
    gets_(b, T_ISSUER,  issuer,  sizeof(issuer));
    gets_(b, T_STR1,    ctype,   sizeof(ctype));   /* 선택: 명시 카드종류 */
    gets_(b, T_STR2,    scheme,  sizeof(scheme));  /* 선택: 명시 스킴 */
    if (channel[0] == 0) strcpy(channel, "POS");
    if (issuer[0] == 0)  strcpy(issuer, "UNKNOWN");
    userlog("[정산심화] 수수료 3층 분해 진입 pid=%ld amt=%ld chan=%s issuer=%s", h_pid, amount, channel, issuer);
    if (h_pid <= 0 && amount <= 0) {
        setl(b, T_RC, 8101); Bchg(b, T_MSG, 0, "매입 ID 또는 (금액+채널) 필수", 0L);
        userlog("[ST_FEEDECOMP] 입력 부족 pid=%ld amt=%ld", h_pid, amount); FAIL(b);
    }
    if (amount < 0) { setl(b, T_RC, 8102); Bchg(b, T_MSG, 0, "매입 금액 음수 불가", 0L); FAIL(b); }

    /* ===== 2) 매입 조회부(미커밋이면 전문값) + 카드종류/스킴 결정 ===== */
    if (h_pid > 0) {
        EXEC SQL SELECT amount, fee, channel, issuer, merchant_id, status, biz_date
            INTO :h_amount, :h_fee, :h_channel, :h_issuer, :h_merch, :h_status, :h_bizdate
            FROM purchase WHERE purchase_id = :h_pid;
        if (sqlca.sqlcode == 100) {
            h_amount = amount; h_fee = feein;
            strncpy(h_channel, channel, sizeof(h_channel)-1); h_channel[sizeof(h_channel)-1] = 0;
            strncpy(h_issuer, issuer, sizeof(h_issuer)-1);   h_issuer[sizeof(h_issuer)-1] = 0;
            userlog("[ST_FEEDECOMP] 체인 신규매입(미커밋) pid=%ld — 전문값으로 분해", h_pid);
        } else if (sqlca.sqlcode < 0) {
            setl(b, T_RC, 8110); Bchg(b, T_MSG, 0, "매입 조회 오류", 0L);
            userlog("[ST_FEEDECOMP] 매입 조회 오류 [%d]", sqlca.sqlcode); FAIL(b);
        }
    } else {
        h_amount = amount; h_fee = feein;
        strncpy(h_channel, channel, sizeof(h_channel)-1); h_channel[sizeof(h_channel)-1] = 0;
        strncpy(h_issuer, issuer, sizeof(h_issuer)-1);   h_issuer[sizeof(h_issuer)-1] = 0;
    }
    if (h_amount <= 0) { setl(b, T_RC, 8103); Bchg(b, T_MSG, 0, "분해 대상 금액이 0 이하", 0L); FAIL(b); }
    /* 카드종류: 명시값 우선, 없으면 매입ID 규칙(하위 3자리 % 10 < 3 → 체크카드) */
    if (ctype[0] == 0) strcpy(ctype, (h_pid > 0 && (h_pid % 10) < 3) ? "CHECK" : "CREDIT");
    if (scheme[0] == 0) strcpy(scheme, "BC");
    strncpy(h_ctype, ctype, sizeof(h_ctype)-1);   h_ctype[sizeof(h_ctype)-1] = 0;
    strncpy(h_scheme, scheme, sizeof(h_scheme)-1); h_scheme[sizeof(h_scheme)-1] = 0;

    /* ===== 3) interchange 요율 조회부 (card_type×channel×SALE) ===== */
    EXEC SQL SELECT rate_bps, fixed_fee INTO :h_icbps, :h_icfix FROM st_interchange_rate
        WHERE card_type = :h_ctype AND mcc = 'DEFAULT' AND channel = :h_channel AND txn_type = 'SALE';
    if (sqlca.sqlcode == 100) {
        /* 채널 미매핑 → DEFAULT 채널 요율로 폴백 */
        EXEC SQL SELECT rate_bps, fixed_fee INTO :h_icbps, :h_icfix FROM st_interchange_rate
            WHERE card_type = :h_ctype AND mcc = 'DEFAULT' AND channel = 'DEFAULT' AND txn_type = 'SALE';
        if (sqlca.sqlcode == 100) { h_icbps = 130; h_icfix = 0;
            userlog("[ST_FEEDECOMP] interchange 요율 미존재 ctype=%s chan=%s — 기본 130bp 적용", h_ctype, h_channel); }
        else if (sqlca.sqlcode < 0) { setl(b, T_RC, 8120); Bchg(b, T_MSG, 0, "interchange 요율 조회 오류", 0L); FAIL(b); }
    } else if (sqlca.sqlcode < 0) { setl(b, T_RC, 8120); Bchg(b, T_MSG, 0, "interchange 요율 조회 오류", 0L); FAIL(b); }

    /* ===== 4) scheme fee 요율 조회부 (scheme×SALE) ===== */
    EXEC SQL SELECT rate_bps, fixed_fee INTO :h_sfbps, :h_sffix FROM st_scheme_fee
        WHERE scheme = :h_scheme AND txn_type = 'SALE';
    if (sqlca.sqlcode == 100) { h_sfbps = 11; h_sffix = 0;
        userlog("[ST_FEEDECOMP] scheme 요율 미존재 scheme=%s — 기본 11bp 적용", h_scheme); }
    else if (sqlca.sqlcode < 0) { setl(b, T_RC, 8130); Bchg(b, T_MSG, 0, "scheme 요율 조회 오류", 0L); FAIL(b); }

    /* ===== 5) 업무규칙 분기부 (3층 산출) ===== */
    h_ic    = h_amount * h_icbps / 10000 + h_icfix;       /* 발급사 귀속 */
    h_sf    = h_amount * h_sfbps / 10000 + h_sffix;       /* 카드망 귀속 */
    h_floor = h_amount * 8 / 10000;                       /* 매입사 최소 마진 8bp */
    h_markup = h_fee - h_ic - h_sf;                       /* 기존 flat fee 잔여 = markup */
    if (h_markup < h_floor) {
        h_markup = h_floor;
        userlog("[ST_FEEDECOMP] markup 하한(8bp) 적용 fee=%ld ic=%ld sf=%ld floor=%ld", h_fee, h_ic, h_sf, h_floor);
    }
    h_mdr = h_ic + h_sf + h_markup;                       /* MDR 합계 */
    userlog("[ST_FEEDECOMP] 3층분해 ic=%ld(%ldbp) sf=%ld(%ldbp) markup=%ld mdr=%ld",
            h_ic, h_icbps, h_sf, h_sfbps, h_markup, h_mdr);

    /* ===== 6) 본처리부 (st_fee_component UPSERT) — 매입ID 있을 때만 영속 ===== */
    if (h_pid > 0) {
        EXEC SQL INSERT INTO st_fee_component
            (purchase_id, amount, interchange, scheme_fee, markup, mdr_total, card_type, scheme)
            VALUES (:h_pid, :h_amount, :h_ic, :h_sf, :h_markup, :h_mdr, :h_ctype, :h_scheme)
            ON CONFLICT (purchase_id) DO UPDATE SET
                amount = excluded.amount, interchange = excluded.interchange,
                scheme_fee = excluded.scheme_fee, markup = excluded.markup,
                mdr_total = excluded.mdr_total, card_type = excluded.card_type,
                scheme = excluded.scheme, computed_at = now();
        if (sqlca.sqlcode < 0) {
            setl(b, T_RC, 8140); Bchg(b, T_MSG, 0, "수수료 분해 UPSERT 실패", 0L);
            userlog("[ST_FEEDECOMP] st_fee_component UPSERT 실패 [%d]", sqlca.sqlcode); FAIL(b);
        }
        persist = 1;
    } else {
        userlog("[ST_FEEDECOMP] 매입ID 없음 — 미리보기(preview) 계산만 수행(영속 생략)");
    }

    /* ===== 7) 감사이력 적재부 (cm_log) + 재검증 ===== */
    snprintf(msgbuf, sizeof(msgbuf), "ST_FEEDECOMP pid=%ld amt=%ld ic=%ld sf=%ld markup=%ld mdr=%ld ctype=%s",
             h_pid, h_amount, h_ic, h_sf, h_markup, h_mdr, h_ctype);
    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, 8150); Bchg(b, T_MSG, 0, "감사 로그 적재 실패", 0L); FAIL(b); }
    if (persist) {
        EXEC SQL SELECT count(*) INTO :h_cnt FROM st_fee_component WHERE purchase_id = :h_pid;
        if (sqlca.sqlcode < 0) { setl(b, T_RC, 8151); Bchg(b, T_MSG, 0, "분해 재검증 조회 오류", 0L); FAIL(b); }
        if (h_cnt <= 0) { setl(b, T_RC, 8152); Bchg(b, T_MSG, 0, "분해 미적재(보상 롤백)", 0L); FAIL(b); }
    }

    /* ===== 8) 응답부 (출력 필드 설정) ===== */
    setl(b, T_AMT1, h_ic);        /* interchange */
    setl(b, T_AMT2, h_sf);        /* scheme_fee  */
    setl(b, T_AMT3, h_markup);    /* markup      */
    setl(b, T_FEE,  h_mdr);       /* mdr_total   */
    Bchg(b, T_STR1, 0, h_ctype, 0L);
    Bchg(b, T_STR2, 0, h_scheme, 0L);
    Bchg(b, T_SVCNAME, 0, "ST_FEEDECOMP", 0L);
    setl(b, T_RC, 0);

    /* ===== 9) 완료 로깅 ===== */
    userlog("[정산심화] 수수료 3층 분해 완료 rc=0 pid=%ld mdr=%ld persist=%ld", h_pid, h_mdr, persist);
    OK(b);
}

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