/*
 * AUTH_SUMMARY.pgc - au 모듈 서비스 AUTH_SUMMARY (one service = one file).
 * 가맹점 당일 승인 집계 upsert (dbio).
 * Moved verbatim from the former inline au_svr.pgc; runs on the caller's XA
 * branch (no EXEC SQL CONNECT). Advertised by au_svr at tpsvrinit.
 */
#include "AUTH_SUMMARY.h"

/*
 * 심화 구현 (AUTH_SUMMARY): 집계 계약(T_MERCHANT/T_BIZDATE ->
 * T_COUNT/T_GROSS)과 au_summary upsert 를 원형 보존하고, 그 앞뒤에 입력검증,
 * 가맹점 마스터 점검, 상태별 세분 집계, 승인율 산출, 부가 응답필드를 덧댄다.
 */
void AUTH_SUMMARY(TPSVCINFO *p)
{
    UBFH *b = (UBFH *)p->data;
    const char *svcname = "AUTH_SUMMARY";
    char merch[64], bizdate[16];
    long rc = 0, rate_bps = 0, fee_amt = 0, vat_amt = 0;
    char nextbiz[16];
    EXEC SQL BEGIN DECLARE SECTION;
    long h_cnt = 0, h_appr = 0, h_dec = 0, h_amt = 0, h_cxl = 0, h_mdr = 0;
    long h_cxl_cnt = 0, h_cxl_full = 0, h_cxl_amt = 0, h_peak_cnt = 0;
    long h_top_cnt = 0, h_stdin = 0;
    char h_merch[64], h_bizdate[16], h_mstat[16];
    char h_peak_hh[8], h_top_reason[64];
    EXEC SQL END DECLARE SECTION;

    memset(h_mstat, 0, sizeof(h_mstat));
    memset(nextbiz, 0, sizeof(nextbiz));
    memset(h_peak_hh, 0, sizeof(h_peak_hh));
    memset(h_top_reason, 0, sizeof(h_top_reason));
    gets_(b, T_MERCHANT, merch, sizeof(merch));
    gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
    userlog("[%s] 진입: 가맹점 당일 집계 merch=%s date=%s", svcname, merch, bizdate);

    /* 1) 입력 검증부 */
    if (merch[0] == 0) { setl(b, T_RC, 8811L);
        Bchg(b, T_MSG, 0, "가맹점ID(T_MERCHANT) 필수", 0L);
        userlog("[%s] 입력검증 실패: 가맹점 누락", svcname); FAIL(b); }
    if (strlen(bizdate) < 8) { setl(b, T_RC, 8812L);
        Bchg(b, T_MSG, 0, "영업일(YYYY-MM-DD) 형식오류", 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;

    /* 2) 마스터 조회부: 가맹점 상태/수수료율 점검 */
    EXEC SQL SELECT status, mdr_bps INTO :h_mstat, :h_mdr
        FROM merchant WHERE merchant_id = :h_merch;
    if (sqlca.sqlcode == 100) { strcpy(h_mstat, "NONE"); rc = 1; }
    else if (sqlca.sqlcode < 0) { setl(b, T_RC, 44L); FAIL(b); }

    /* 3) 업무규칙 분기부: 상태 세분 집계 (보존 계약의 상위집합) */
    EXEC SQL SELECT count(*),
                    count(*) FILTER (WHERE status = 'A'),
                    count(*) FILTER (WHERE status = 'D'),
                    count(*) FILTER (WHERE status = 'C'),
                    coalesce(sum(amount),0)
        INTO :h_cnt, :h_appr, :h_dec, :h_cxl, :h_amt
        FROM au_authorization WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 45L); FAIL(b); }

    if (h_cnt == 0) { rc = (rc == 1 ? 1 : 0); rate_bps = 0; }
    else { rate_bps = h_appr * 10000L / h_cnt; }

    /* 4) 본처리부: au_summary upsert (원형 계약 보존) */
    if (audb_upsert_auth_summary(merch, bizdate, h_cnt, h_appr, h_dec, h_amt) < 0) {
        setl(b, T_RC, 46L); Bchg(b, T_MSG, 0, "집계 upsert 실패", 0L); FAIL(b); }

    /* 5) 이력/재집계부: 저장결과 재조회로 정합성 확인 */
    EXEC SQL SELECT auth_count, auth_amount INTO :h_cnt, :h_amt
        FROM au_summary WHERE merchant_id = :h_merch AND biz_date = :h_bizdate;
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 47L); FAIL(b); }

    /* 6) 요약부: 승인율/취소건 등 부가필드 */
    setl(b, T_ARG1, rate_bps);
    setl(b, T_ARG2, h_dec);
    setl(b, T_ARG3, h_cxl);
    Bchg(b, T_STATUS, 0, h_mstat, 0L);

    /* ---------------------------------------------------------------
     * 6-a) 부가 집계부 (AUTH_SUMMARY): 가맹점 일일 마감에서 함께 보는
     *      취소/시간대/거절사유/대행 지표를 SELECT 로 덧붙인다. au_summary
     *      본 계약(T_COUNT/T_GROSS)과 upsert 결과는 이미 확정되어 있으므로
     *      아래 구간은 응답을 풍부하게 할 뿐 원장을 바꾸지 않는다.
     * --------------------------------------------------------------- */

    /* 부가 집계 (1): 당일 취소 원장 - 전액/부분 건수와 취소금액 */
    EXEC SQL SELECT count(*), count(*) FILTER (WHERE c.cancel_type = 'FULL'),
                    coalesce(sum(c.amount),0)
        INTO :h_cxl_cnt, :h_cxl_full, :h_cxl_amt
        FROM au_cancel c
        JOIN au_authorization a ON a.auth_id = c.auth_id
        WHERE a.merchant_id = :h_merch AND c.biz_date = :h_bizdate;
    if (sqlca.sqlcode < 0) { h_cxl_cnt = 0; h_cxl_full = 0; h_cxl_amt = 0; }
    setl(b, T_ARG4, h_cxl_cnt);
    setl(b, T_ARG5, h_cxl_amt);

    /* 부가 집계 (2): 피크 시간대 - 승인 접수가 가장 몰린 시(HH24) */
    EXEC SQL SELECT coalesce(to_char(created_at,'HH24'),'--'), count(*)
        INTO :h_peak_hh, :h_peak_cnt
        FROM au_authorization
        WHERE merchant_id = :h_merch AND biz_date = :h_bizdate
        GROUP BY to_char(created_at,'HH24')
        ORDER BY count(*) DESC LIMIT 1;
    if (sqlca.sqlcode != 0) { strcpy(h_peak_hh, "--"); h_peak_cnt = 0; }
    Bchg(b, T_STR1, 0, h_peak_hh, 0L);
    setl(b, T_ARG6, h_peak_cnt);

    /* 부가 집계 (3): 최다 거절사유 - 승인율 저하 원인 파악 */
    EXEC SQL SELECT coalesce(decline_reason,'NONE'), count(*)
        INTO :h_top_reason, :h_top_cnt
        FROM au_authorization
        WHERE merchant_id = :h_merch AND biz_date = :h_bizdate AND status = 'D'
        GROUP BY decline_reason ORDER BY count(*) DESC LIMIT 1;
    if (sqlca.sqlcode != 0) { strcpy(h_top_reason, "NONE"); h_top_cnt = 0; }
    Bchg(b, T_REASON, 0, h_top_reason, 0L);

    /* 부가 집계 (4): 대행승인(STANDIN) 비중 - 발급사 장애 영향도 */
    EXEC SQL SELECT count(*) INTO :h_stdin FROM au_authorization
        WHERE merchant_id = :h_merch AND biz_date = :h_bizdate
          AND auth_type = 'STANDIN';
    if (sqlca.sqlcode < 0) h_stdin = 0;
    setl(b, T_ARG7, h_stdin);

    /* 부가 집계 (5): 정산 참고치 - MDR 수수료/부가세/차기 영업일 */
    if (h_amt > 0 && h_mdr > 0) {
        fee_amt = acq_fee(h_amt, h_mdr);
        vat_amt = acq_vat(fee_amt);
    }
    setl(b, T_FEE, fee_amt);
    setl(b, T_TAX, vat_amt);
    if (acq_next_bizday(bizdate, nextbiz) == 0)
        Bchg(b, T_STR2, 0, nextbiz, 0L);

    /* 부가 집계 (6): 마감 판정 - 승인율/취소율 구간으로 요약 등급 */
    if (h_cnt > 0 && h_cxl_cnt * 10000L / h_cnt >= 1000L) rc = (rc ? rc : 2);
    else if (rate_bps > 0 && rate_bps < 8000L) rc = (rc ? rc : 3);
    userlog("[%s] 부가집계 취소=%ld건/%ld원 피크=%s(%ld) 대행=%ld 수수료=%ld",
            svcname, h_cxl_cnt, h_cxl_amt, h_peak_hh, h_peak_cnt, h_stdin, fee_amt);

    /* 7) 예외/보상: upsert 실패는 FAIL→XA 롤백. 위 부가집계는 조회 전용이라
     *    실패해도 0 으로 낮춰 담고 마감 응답 자체는 계속 진행한다. */
    /* 8) 응답부: 보존 계약 필드(T_COUNT/T_GROSS) */
    setl(b, T_COUNT, h_cnt);              /* 승인건수(전체 집계건수, 보존) */
    setl(b, T_GROSS, h_amt);             /* 승인금액 (보존) */
    setl(b, T_RC, rc);
    /* 9) 완료 로깅 */
    userlog("[%s] 완료 merch=%s date=%s cnt=%ld appr=%ld amt=%ld rate=%ldbps",
            svcname, merch, bizdate, h_cnt, h_appr, h_amt, rate_bps);
    OK(b);
}
