/*
 * MM_ONBOARD.pgc - mm 모듈 서비스 MM_ONBOARD (가맹점 심사 진행 / 상태기계).
 * 업무: mm_application 의 심사 상태를 전이한다. 상태기계는 아래 전이만 허용하고
 *       그 외 전이는 부적법(不適法)으로 거부한다.
 *         RECEIVED    --UNDERWRITE--> UNDERWRITING
 *         UNDERWRITING --APPROVE---->  APPROVED   (merchant_id 발급/decision_at/reviewer)
 *         UNDERWRITING --REJECT----->  REJECTED   (reject_reason/decision_at/reviewer)
 *       APPROVED/REJECTED 는 종단 상태로 모든 전이를 거부한다.
 * 입력: T_ID1(app_id), T_STR1(action), T_STR3(reviewer 선택), T_REASON(반려사유 선택).
 * 출력: T_STATUS=새 status, T_STR2=merchant_id, T_RC.
 * 부적법 전이는 T_RC/T_MSG 세팅 후 FAIL(글로벌 트랜잭션 롤백).
 * 호출자 XA 브랜치에서 수행(EXEC SQL CONNECT 없음). mm_svr 가 tpsvrinit 에서 광고.
 */
#include "MM_ONBOARD.h"

/* MM_ONBOARD - 가맹점 심사 상태기계 전이. */
void MM_ONBOARD(TPSVCINFO *p)
{
    UBFH *b = (UBFH *)p->data;
    char  action[24], reviewer[64], reason[160];
    int   legal = 0;
    EXEC SQL BEGIN DECLARE SECTION;
    long  h_app_id, h_logid;
    char  h_action[24], h_cur[16], h_new[16], h_mid[32];
    char  h_reviewer[64], h_reason[160], h_svc[24], h_msg[200];
    EXEC SQL END DECLARE SECTION;

    /* 지역/호스트 변수 초기화 (DECLARE SECTION 밖) */
    h_app_id = h_logid = 0;
    action[0] = reviewer[0] = reason[0] = 0;
    h_action[0] = h_cur[0] = h_new[0] = h_mid[0] = 0;
    h_reviewer[0] = h_reason[0] = 0;
    strcpy(h_svc, "MM_ONBOARD");
    userlog("[MM_ONBOARD] 심사 진행 진입");

    /* [1] 입력 검증부 -------------------------------------------------- */
    h_app_id = getl(b, T_ID1);
    if (h_app_id <= 0) {
        setl(b, T_RC, 7001);
        Bchg(b, T_MSG, 0, "신청 ID(app_id) 필수", 0L);
        userlog("[MM_ONBOARD] app_id 검증 실패 id=%ld", h_app_id);
        FAIL(b);
    }
    gets_(b, T_STR1, action, sizeof(action));
    if (strcmp(action, "UNDERWRITE") != 0 &&
        strcmp(action, "APPROVE")    != 0 &&
        strcmp(action, "REJECT")     != 0) {
        setl(b, T_RC, 7002);
        Bchg(b, T_MSG, 0, "action 은 UNDERWRITE/APPROVE/REJECT 중 하나여야 함", 0L);
        userlog("[MM_ONBOARD] 부적합 action=[%s]", action);
        FAIL(b);
    }
    strncpy(h_action, action, sizeof(h_action)-1); h_action[sizeof(h_action)-1] = 0;

    /* reviewer / reject 사유(선택 입력) */
    gets_(b, T_STR3, reviewer, sizeof(reviewer));
    if (reviewer[0] == 0) strcpy(reviewer, "AUTO");
    strncpy(h_reviewer, reviewer, sizeof(h_reviewer)-1); h_reviewer[sizeof(h_reviewer)-1] = 0;
    gets_(b, T_REASON, reason, sizeof(reason));

    /* [2] 현재 상태 조회부 -------------------------------------------- */
    EXEC SQL SELECT status, coalesce(merchant_id,'')
        INTO :h_cur, :h_mid
        FROM mm_application WHERE app_id = :h_app_id;
    if (sqlca.sqlcode == 100) {
        setl(b, T_RC, 7003);
        Bchg(b, T_MSG, 0, "신청 원장 미존재", 0L);
        userlog("[MM_ONBOARD] 신청 미존재 app_id=%ld", h_app_id);
        FAIL(b);
    } else if (sqlca.sqlcode < 0) {
        userlog("[MM_ONBOARD] 신청 조회 오류 [%d]", sqlca.sqlcode);
        FAIL(b);
    }
    userlog("[MM_ONBOARD] app_id=%ld 현재상태=%s action=%s", h_app_id, h_cur, h_action);

    /* [3] 상태기계 전이 판정부 (부적법 전이 거부) --------------------- */
    if (strcmp(h_action, "UNDERWRITE") == 0) {
        if (strcmp(h_cur, "RECEIVED") == 0) { strcpy(h_new, "UNDERWRITING"); legal = 1; }
    } else if (strcmp(h_action, "APPROVE") == 0) {
        if (strcmp(h_cur, "UNDERWRITING") == 0) { strcpy(h_new, "APPROVED"); legal = 1; }
    } else if (strcmp(h_action, "REJECT") == 0) {
        if (strcmp(h_cur, "UNDERWRITING") == 0) { strcpy(h_new, "REJECTED"); legal = 1; }
    }
    if (!legal) {
        setl(b, T_RC, 7010);
        snprintf(h_msg, sizeof(h_msg),
                 "부적법 전이 거부: %s 상태에서 %s 불가", h_cur, h_action);
        Bchg(b, T_MSG, 0, h_msg, 0L);
        userlog("[MM_ONBOARD] %s", h_msg);
        FAIL(b);
    }

    /* [4] 본처리부: 상태별 UPDATE ------------------------------------- */
    if (strcmp(h_new, "UNDERWRITING") == 0) {
        EXEC SQL UPDATE mm_application SET status = 'UNDERWRITING'
            WHERE app_id = :h_app_id;
        if (sqlca.sqlcode < 0) { userlog("[MM_ONBOARD] UNDERWRITING 갱신 실패"); FAIL(b); }
        h_mid[0] = 0;   /* 아직 MID 미발급 */
    } else if (strcmp(h_new, "APPROVED") == 0) {
        /* merchant_id 발급: 'M' + app_id zero-padding (호스트변수 캐스팅 회피, C에서 조립) */
        snprintf(h_mid, sizeof(h_mid), "M%09ld", h_app_id);
        EXEC SQL UPDATE mm_application
            SET status = 'APPROVED', merchant_id = :h_mid,
                reviewer = :h_reviewer, decision_at = now()
            WHERE app_id = :h_app_id;
        if (sqlca.sqlcode < 0) { userlog("[MM_ONBOARD] APPROVED 갱신 실패"); FAIL(b); }
        userlog("[MM_ONBOARD] 승인 app_id=%ld mid=[%s] reviewer=[%s]",
                h_app_id, h_mid, h_reviewer);
    } else { /* REJECTED */
        if (reason[0] == 0) strcpy(reason, "심사 반려");
        strncpy(h_reason, reason, sizeof(h_reason)-1); h_reason[sizeof(h_reason)-1] = 0;
        EXEC SQL UPDATE mm_application
            SET status = 'REJECTED', reviewer = :h_reviewer,
                reject_reason = :h_reason, decision_at = now()
            WHERE app_id = :h_app_id;
        if (sqlca.sqlcode < 0) { userlog("[MM_ONBOARD] REJECTED 갱신 실패"); FAIL(b); }
        h_mid[0] = 0;
        userlog("[MM_ONBOARD] 반려 app_id=%ld reason=[%s]", h_app_id, h_reason);
    }

    /* [5] 이력/감사 적재부 (cm_log) ----------------------------------- */
    EXEC SQL SELECT nextval('cm_log_seq') INTO :h_logid;
    if (sqlca.sqlcode < 0) { userlog("[MM_ONBOARD] 로그 시퀀스 실패"); FAIL(b); }
    snprintf(h_msg, sizeof(h_msg), "MM_ONBOARD app=%ld %s: %s -> %s mid=%s",
             h_app_id, h_action, h_cur, h_new, h_mid[0] ? h_mid : "-");
    EXEC SQL INSERT INTO cm_log (log_id, svc_name, log_level, msg, biz_date)
        VALUES (:h_logid, :h_svc, 'I', :h_msg, current_date);
    if (sqlca.sqlcode < 0) { userlog("[MM_ONBOARD] 감사 로그 적재 실패 [%d]", sqlca.sqlcode); FAIL(b); }

    /* [6] 응답부 (출력 필드 설정) ------------------------------------- */
    Bchg(b, T_STATUS, 0, h_new, 0L);
    Bchg(b, T_STR2, 0, h_mid, 0L);   /* 승인시 발급 MID, 그 외 빈값 */
    setl(b, T_RC, 0);

    /* [7] 완료 로깅 --------------------------------------------------- */
    userlog("[MM_ONBOARD] 전이 완료 app_id=%ld %s -> %s", h_app_id, h_cur, h_new);
    OK(b);
}

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