/*
 * ACQ_STATUS.pgc - ac 모듈 서비스 ACQ_STATUS (one service = one file).
 * 매입 상태 조회: 매입 ID 로 현재 상태를 읽어 돌려주고, 상태에 따른 진행 단계와
 * 부수 이력(취소/조정/미매입) 건수를 함께 응답한다.
 * 입출력 계약 보존: 입력 T_PURCHASE_ID, 출력 T_STATUS (acdb_get_status 사용).
 * Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
 */
#include "ACQ_STATUS.h"

void ACQ_STATUS(TPSVCINFO *p)
{
    UBFH *b = (UBFH *)p->data;
    const char *SVC = "ACQ_STATUS";
    char st[4], logmsg[256];
    long pid, stage = 0;
    EXEC SQL BEGIN DECLARE SECTION;
    long h_pid = 0, h_can = 0, h_adj = 0, h_unm = 0, h_apr = 0, h_logid = 0;
    long h_amt = 0, h_fee = 0, h_net = 0, h_ctx = 0, h_led = 0, h_set = 0, h_inst = 0;
    char h_bizdate[16], h_merch[64], h_chan[16], h_logmsg[256];
    EXEC SQL END DECLARE SECTION;

    userlog("%s 진입: 매입 상태 조회 요청", SVC);

    /* 1) 입력 검증부 */
    pid = getl(b, T_PURCHASE_ID);
    if (pid <= 0) {
        Bchg(b, T_MSG, 0, "매입 ID 오류", 0L); setl(b, T_RC, 102); FAIL(b);
    }
    h_pid = pid;

    /* 2) 마스터/상태 조회부: 계약 보존을 위해 dbio 헬퍼로 상태를 읽는다 */
    st[0] = 0;
    if (acdb_get_status(pid, st) < 0) {
        userlog("%s: 상태 조회 실패 pid=%ld", SVC, pid);
        Bchg(b, T_MSG, 0, "상태 조회 실패", 0L); setl(b, T_RC, 111); FAIL(b);
    }
    EXEC SQL SELECT merchant_id, amount, fee, net, channel, biz_date::text
        INTO :h_merch, :h_amt, :h_fee, :h_net, :h_chan, :h_bizdate
        FROM purchase WHERE purchase_id = :h_pid;
    if (sqlca.sqlcode < 0) {
        userlog("%s: 매입원장 조회 실패 [%d]", SVC, sqlca.sqlcode);
        setl(b, T_RC, 90); FAIL(b);
    }
    if (sqlca.sqlcode == 100) {
        Bchg(b, T_MSG, 0, "매입 미존재", 0L); setl(b, T_RC, 111); FAIL(b);
    }
    if (h_bizdate[0] == 0) strcpy(h_bizdate, "2026-07-19");
    userlog("%s 컨텍스트: pid=%ld merch=%s 상태=%s", SVC, pid, h_merch, st);

    /* 부수 이력 건수 로드 */
    EXEC SQL SELECT count(*) INTO :h_can FROM ac_cancel WHERE purchase_id = :h_pid;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 90); FAIL(b); }
    EXEC SQL SELECT count(*) INTO :h_adj FROM ac_fee_adj WHERE purchase_id = :h_pid;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 90); FAIL(b); }
    EXEC SQL SELECT count(*) INTO :h_unm FROM ac_unmatch WHERE purchase_id = :h_pid;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 90); FAIL(b); }
    EXEC SQL SELECT count(*) INTO :h_apr FROM approval WHERE purchase_id = :h_pid;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 90); FAIL(b); }

    /* 정산/원장/할부 연계 컨텍스트 로드 */
    EXEC SQL SELECT count(*) INTO :h_set FROM settlement WHERE purchase_id = :h_pid;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 90); FAIL(b); }
    EXEC SQL SELECT count(*), coalesce(sum(amount),0) INTO :h_led, :h_ctx
        FROM ledger WHERE purchase_id = :h_pid;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 90); FAIL(b); }
    EXEC SQL SELECT count(*) INTO :h_inst FROM ac_install WHERE purchase_id = :h_pid;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 90); FAIL(b); }
    userlog("%s 연계: 정산=%ld 원장=%ld 할부=%ld", SVC, h_set, h_led, h_inst);

    /* 3) 업무규칙 분기부: 상태코드를 진행 단계로 환산 (3+ 분기) */
    if (strcmp(st, "A") == 0) {
        stage = 1; Bchg(b, T_MSG, 0, "접수 단계", 0L);
    } else if (strcmp(st, "M") == 0) {
        stage = 2; Bchg(b, T_MSG, 0, "대사완료 단계", 0L);
    } else if (strcmp(st, "S") == 0) {
        stage = 3; Bchg(b, T_MSG, 0, "정산완료 단계", 0L);
    } else if (strcmp(st, "H") == 0) {
        stage = 4; Bchg(b, T_MSG, 0, "보류 상태", 0L);
    } else if (strcmp(st, "C") == 0 || strcmp(st, "V") == 0) {
        stage = 5; Bchg(b, T_MSG, 0, "종료(취소/무효) 상태", 0L);
    } else {
        stage = 0; Bchg(b, T_MSG, 0, "기타 상태", 0L);
    }

    /* 7) 예외/보상부: 상태와 이력의 정합 감시 */
    if (strcmp(st, "S") == 0 && h_unm > 0)
        userlog("%s 경보: 정산완료건에 미매입 이력 %ld 건", SVC, h_unm);
    if (h_apr == 0)
        userlog("%s 경보: pid=%ld 승인 이력 없음", SVC, pid);
    if (strcmp(st, "S") == 0 && h_set == 0)
        userlog("%s 경보: 정산완료건에 정산행 없음 pid=%ld", SVC, pid);
    if (strcmp(st, "C") == 0 && h_can == 0)
        userlog("%s 경보: 취소건에 취소이력 없음 pid=%ld", SVC, pid);
    if (h_amt != h_fee + h_net)
        userlog("%s 경보: 금액 정합 불일치 pid=%ld (%ld <> %ld+%ld)", SVC, pid, h_amt, h_fee, h_net);

    /* 5) 이력/감사 적재부 */
    snprintf(logmsg, sizeof(logmsg), "상태조회 pid=%ld 상태=%s 단계=%ld 취소=%ld 조정=%ld",
             pid, st, stage, h_can, h_adj);
    strncpy(h_logmsg, logmsg, sizeof(h_logmsg)-1); h_logmsg[sizeof(h_logmsg)-1] = 0;
    EXEC SQL SELECT nextval('cm_log_seq') INTO :h_logid;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 90); FAIL(b); }
    EXEC SQL INSERT INTO cm_log (log_id, svc_name, log_level, msg, biz_date)
        VALUES (:h_logid, 'ACQ_STATUS', 'I', :h_logmsg, :h_bizdate);
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 90); FAIL(b); }

    /* 9) 사후 검증부: 당일 처리 이력 자기 점검 */
    EXEC SQL SELECT count(*) INTO :h_ctx FROM cm_log
        WHERE svc_name = 'ACQ_STATUS' AND biz_date = :h_bizdate;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 90); FAIL(b); }
    if (h_ctx <= 0) {
        userlog("%s 경보: 처리 이력이 적재되지 않음", SVC);
        Bchg(b, T_MSG, 0, "이력 적재 확인 실패", 0L);
        setl(b, T_RC, 89); FAIL(b);
    }
    if (h_ctx > 1000)
        userlog("%s 경보: 당일 조회 %ld 회로 과다", SVC, h_ctx);

    /* 8) 응답부 (계약 보존: T_STATUS) */
    Bchg(b, T_STATUS, 0, st, 0L);
    Bchg(b, T_MERCHANT, 0, h_merch, 0L);
    Bchg(b, T_CHANNEL, 0, h_chan, 0L);
    setl(b, T_AMOUNT, h_amt);
    setl(b, T_FEE, h_fee);
    setl(b, T_NET, h_net);
    setl(b, T_ARG1, stage);
    setl(b, T_ARG2, h_can);
    setl(b, T_ARG3, h_adj);
    setl(b, T_ARG4, h_unm);
    setl(b, T_ARG5, h_apr);
    setl(b, T_ARG6, h_set);
    setl(b, T_ARG7, h_led);
    setl(b, T_ARG8, h_inst);
    setl(b, T_AMT1, h_ctx);
    setl(b, T_RC, 0);
    userlog("%s 완료: pid=%ld 상태=%s 단계=%ld", SVC, pid, st, stage);
    OK(b);
}
