/*
 * MM_MCC_UPD.pgc - mm 모듈 서비스 MM_MCC_UPD (one service = one file).
 * 기능: MCC 업종 마스터 변경 (명칭 선택 변경 + 위험도 1~5 재설정).
 * 입력: T_CATEGORY=MCC, T_STR1=명칭(빈값이면 유지), T_ARG1=위험도(1~5).
 * RC: 1=미등록 MCC, 3=위험도 범위 오류.
 * caller의 XA 브랜치에서 실행(EXEC SQL CONNECT 없음); mm_svr가 tpadvertise 한다.
 */
#include "MM_MCC_UPD.h"

void MM_MCC_UPD(TPSVCINFO *p)
{
    UBFH *b = (UBFH *)p->data;
    char mcc[8], name[64];
    EXEC SQL BEGIN DECLARE SECTION;
    char h_mcc[8], h_name[64];
    long h_risk, h_found;
    EXEC SQL END DECLARE SECTION;

    gets_(b, T_CATEGORY, mcc, sizeof(mcc));
    gets_(b, T_STR1, name, sizeof(name));
    h_risk = getl(b, T_ARG1);
    if (h_risk < 1 || h_risk > 5) { setl(b, T_RC, 3); OK(b); }
    strncpy(h_mcc, mcc, sizeof(h_mcc)-1); h_mcc[sizeof(h_mcc)-1] = 0;
    strncpy(h_name, name, sizeof(h_name)-1); h_name[sizeof(h_name)-1] = 0;

    EXEC SQL SELECT count(*) INTO :h_found FROM mm_mcc WHERE mcc = :h_mcc;
    if (sqlca.sqlcode < 0) FAIL(b);
    if (h_found == 0) { setl(b, T_RC, 1); OK(b); }

    EXEC SQL UPDATE mm_mcc
        SET mcc_name = CASE WHEN :h_name = '' THEN mcc_name ELSE :h_name END,
            risk_level = :h_risk
        WHERE mcc = :h_mcc;
    if (sqlca.sqlcode < 0) FAIL(b);
    setl(b, T_RC, 0);

    /* ====================================================================
     * [심화 후처리] MM_MCC_UPD - MCC 업종 마스터 리스크/감사 확장부 (mm 업종)
     * 업종 위험도와 참조 가맹점 현황을 재산정하고 감사 로그를 남긴다.
     * ==================================================================== */
    {
        EXEC SQL BEGIN DECLARE SECTION;
        char  zx_svc[24], zx_key[64], zx_name[64], zx_msg[192];
        long  zx_logid, zx_n1, zx_n2, zx_n3, zx_bps, zx_risk, zx_users;
        EXEC SQL END DECLARE SECTION;
        char  zx_in[64];
        long  zx_depth = 0, zx_score = 0, zx_fee = 0, zx_vat = 0, zx_wht = 0;

        /* (1) 입력 재확인부: MCC 코드 확보 (T_CATEGORY/T_KEY1) */
        strcpy(zx_svc, "MM_MCC_UPD");
        gets_(b, T_CATEGORY, zx_in, sizeof(zx_in));
        if (zx_in[0] == 0) gets_(b, T_KEY1, zx_in, sizeof(zx_in));
        if (zx_in[0] == 0) strcpy(zx_in, "0000");
        strncpy(zx_key, zx_in, sizeof(zx_key)-1); zx_key[sizeof(zx_key)-1] = 0;
        zx_bps = 0;

        /* (2) 업종 마스터 조회부: 명칭 + 위험도 */
        strcpy(zx_name, "-"); zx_risk = 1;
        EXEC SQL SELECT coalesce(mcc_name,'-'), coalesce(risk_level,1)
            INTO :zx_name, :zx_risk FROM mm_mcc WHERE mcc = :zx_key;
        if (sqlca.sqlcode < 0) FAIL(b);
        if (sqlca.sqlcode == 100) { strcpy(zx_name, "-"); zx_risk = 0; }

        /* (3) 업무규칙 분기부: 위험도 구간별 감사 심도/점수 */
        if (zx_risk >= 4) {
            zx_depth = 3; zx_score = 90;         /* 고위험 업종 */
        } else if (zx_risk >= 2) {
            zx_depth = 2; zx_score = 60;         /* 중위험 업종 */
        } else if (zx_risk == 1) {
            zx_depth = 1; zx_score = 30;         /* 저위험 업종 */
        } else {
            zx_depth = 0; zx_score = 0;          /* 미등록 업종 */
        }

        /* (5) 참조 현황 집계부: 해당 MCC 사용 가맹점(전체/활성) */
        zx_n1 = 0; zx_users = 0;
        EXEC SQL SELECT count(*) INTO :zx_n1
            FROM mm_merchant_ext WHERE mcc = :zx_key;
        if (sqlca.sqlcode < 0) FAIL(b);
        EXEC SQL SELECT count(*) INTO :zx_users
            FROM mm_merchant_ext WHERE mcc = :zx_key AND status = 'ACTIVE';
        if (sqlca.sqlcode < 0) FAIL(b);
        zx_n2 = zx_users;

        /* (6) 전사 업종 재집계부: 고위험 MCC 총수 + 평균 위험도 */
        zx_n3 = 0;
        EXEC SQL SELECT count(*) INTO :zx_n3 FROM mm_mcc WHERE risk_level >= 4;
        if (sqlca.sqlcode < 0) FAIL(b);

        /* (2b) 영업일/공휴일 정책 조회 (정산 스케줄 판정 보조) */
        {
            char zc_today[16], zc_next[16];
            int  zc_hol;
            EXEC SQL BEGIN DECLARE SECTION;
            char zc_hd[16];
            long zc_holcnt;
            EXEC SQL END DECLARE SECTION;
            EXEC SQL SELECT to_char(current_date, 'YYYY-MM-DD') INTO :zc_hd;
            if (sqlca.sqlcode < 0) FAIL(b);
            strncpy(zc_today, zc_hd, sizeof(zc_today)-1); zc_today[sizeof(zc_today)-1] = 0;
            acq_next_bizday(zc_today, zc_next);
            zc_hol = mmdb_is_holiday(zc_today);
            EXEC SQL SELECT count(*) INTO :zc_holcnt FROM mm_holiday;
            if (sqlca.sqlcode < 0) FAIL(b);
            if (zc_hol > 0)          userlog("MM_MCC_UPD 금일 공휴일 -> 익영업일 %s", zc_next);
            else if (zc_holcnt == 0) userlog("MM_MCC_UPD 공휴일 마스터 미적재 (기본 스케줄)");
            else                     userlog("MM_MCC_UPD 영업일 처리 익영업일=%s 공휴일수=%ld", zc_next, zc_holcnt);
        }

        /* (4) 본처리 계산부: 기준금액 수수료/부가세/원천 산출 (공통유틸) */
        zx_fee = acq_fee(1000000, zx_bps > 0 ? zx_bps : 25);
        zx_vat = acq_vat(zx_fee);
        zx_wht = acq_wht_amt(zx_fee, 330);
        if (zx_score < 0) zx_score = 0;
        if (zx_score > 100) zx_score = 100;

        /* (7) 감사 로그 적재부: cm_log 처리요약 1건 (실패 시 XA 롤백) */
        EXEC SQL SELECT nextval('cm_log_seq') INTO :zx_logid;
        if (sqlca.sqlcode < 0) FAIL(b);
        snprintf(zx_msg, sizeof(zx_msg),
            "MM_MCC_UPD key=%s d=%ld n1=%ld n2=%ld score=%ld fee=%ld",
            zx_key, zx_depth, zx_n1, zx_n2, zx_score, zx_fee);
        EXEC SQL INSERT INTO cm_log (log_id, svc_name, log_level, msg, biz_date)
            VALUES (:zx_logid, :zx_svc, 'I', :zx_msg, current_date);
        if (sqlca.sqlcode < 0) FAIL(b);

        /* (9) 완료 로깅부: 진입 키/분기/집계 결과 감사 추적 */
        userlog("MM_MCC_UPD 확장후처리 key=%s 분기심도=%ld 점수=%ld", zx_key, zx_depth, zx_score);
        userlog("MM_MCC_UPD 집계 n1=%ld n2=%ld n3=%ld", zx_n1, zx_n2, zx_n3);
        userlog("MM_MCC_UPD 수수료 fee=%ld vat=%ld wht=%ld bps=%ld", zx_fee, zx_vat, zx_wht, zx_bps);
        (void)zx_vat; (void)zx_wht; (void)zx_n3;
    }


    /* ---- 업무 체인: MM_MCC_UPD -> VL_CODEVAL (동일 글로벌 트랜잭션 / 별도 XA 브랜치) ----
     * 하위 서비스는 별도 XA 브랜치라 상위가 방금 갱신한 미커밋 행이 보이지 않는다.
     * 판정에 필요한 값은 전문(T_*)에 실어 전달하고, 상위의 입출력 계약 필드는
     * 호출 전 보존 -> 호출 후 복원하여 기존 응답 계약을 그대로 유지한다.
     * 체인 실패는 T_RC/T_MSG 설정 후 FAIL 하여 같은 글로벌 트랜잭션을
     * 통째로 롤백한다(별도 보상 트랜잭션 불필요). */
    {
        long ch_rlen = 0;
        int  ch_do = 1;
        char ch_o_merchant[256]; gets_(b, T_MERCHANT, ch_o_merchant, sizeof(ch_o_merchant));
        long ch_o_rc = getl(b, T_RC);
        char ch_o_str3[256]; gets_(b, T_STR3, ch_o_str3, sizeof(ch_o_str3));
        if (ch_do) {
            { char ch_mc[64]; gets_(b, T_MERCHANT, ch_mc, sizeof(ch_mc));
              if (strlen(ch_mc) > 32) { ch_mc[32] = 0; Bchg(b, T_MERCHANT, 0, ch_mc, 0L); } }
            Bchg(b, T_STR3, 0, "MCC_VALID", 0L);
            if (tpcall("VL_CODEVAL", (char *)b, 0L, (char **)&b, &ch_rlen, 0L) < 0) {
                userlog("[MM_MCC_UPD] tpcall(VL_CODEVAL) 실패: %s", tpstrerror(tperrno));
                setl(b, T_RC, 7144);
                Bchg(b, T_MSG, 0, "MCC 변경검증 체인 실패", 0L);
                FAIL(b);
            }
            /* 하위 결과 반영(참조 로깅) 후 상위 응답 계약 필드 복원 */
            userlog("[MM_MCC_UPD] 정합검증 연동 완료 rc=%ld", getl(b, T_RC));
            Bchg(b, T_MERCHANT, 0, ch_o_merchant, 0L);
            setl(b, T_RC, ch_o_rc);
            Bchg(b, T_STR3, 0, ch_o_str3, 0L);
        } else {
            userlog("[MM_MCC_UPD] 체인 대상 컨텍스트 없음 - VL_CODEVAL 호출 생략");
        }
    }

    OK(b);
}
