/*
 * AUTH_3DS.pgc - au 모듈 서비스 AUTH_3DS (one service = one file).
 * 3DS/SCA 비대면 인증결과 기록·판정: 입력 ECI 를 인증상태(auth_status)와
 *   책임주체(liability)로 매핑하여 au_3ds 원장에 적재한다.
 *     ECI 05 → Y(완전인증) / ISSUER(책임전환)
 *     ECI 06 → A(시도)     / ISSUER(책임전환)
 *     ECI 07 → N(미인증)   / MERCHANT(가맹점 책임)
 *     그 외  → U(불가)     / MERCHANT
 * 처리단계: 입력검증 -> 매입/기존인증 조회 -> ECI 판정분기 -> 본처리(INSERT) ->
 *   적재 재검증 -> 응답 -> 로깅.
 * 호출자 XA 브랜치에서 수행(EXEC SQL CONNECT 없음). au_svr 가 tpsvrinit 에서 광고.
 * XA 격리: 체인 내 미커밋 매입은 이 브랜치에서 안 보일 수 있으므로 조회 미존재(100)는
 *   정상 흐름으로 간주하고 FAIL 하지 않는다(owner-writes 규율, RECONCILE 패턴).
 */
#include "AUTH_3DS.h"

/* AUTH_3DS - 3DS/SCA 인증결과 기록·판정. */
void AUTH_3DS(TPSVCINFO *p)
{
    UBFH *b = (UBFH *)p->data;
    const char *svcname = "AUTH_3DS";
    /* ---- 지역 스크래치 (DECLARE SECTION 밖에서 초기화) ---- */
    long rc = 0;
    char inbuf[16];

    EXEC SQL BEGIN DECLARE SECTION;
    long h_pid;
    char h_eci[8];
    char h_astat[8];
    char h_liab[16];
    char h_ver[16];
    long h_tds;
    long h_prior;
    long h_vcnt;
    long h_pcnt;
    EXEC SQL END DECLARE SECTION;

    memset(inbuf, 0, sizeof(inbuf));
    h_pid = 0; h_tds = 0; h_prior = 0; h_vcnt = 0; h_pcnt = 0;
    memset(h_eci, 0, sizeof(h_eci)); memset(h_astat, 0, sizeof(h_astat));
    memset(h_liab, 0, sizeof(h_liab)); memset(h_ver, 0, sizeof(h_ver));
    strcpy(h_ver, "2.2.0");
    userlog("[%s] 진입: 3DS/SCA 인증결과 기록·판정", svcname);

    /* ===== 1) 입력 검증부 ===== */
    h_pid = getl(b, T_PURCHASE_ID);
    gets_(b, T_STR1, inbuf, sizeof(inbuf));
    if (h_pid <= 0) {
        setl(b, T_RC, 8401L); Bchg(b, T_MSG, 0, "매입 ID(purchase_id) 필수", 0L);
        userlog("[%s] 입력검증 실패: pid=%ld", svcname, h_pid); FAIL(b);
    }
    if (inbuf[0] == 0) {
        setl(b, T_RC, 8402L); Bchg(b, T_MSG, 0, "ECI 필수 누락", 0L);
        userlog("[%s] 입력검증 실패: ECI 누락 pid=%ld", svcname, h_pid); FAIL(b);
    }
    strncpy(h_eci, inbuf, sizeof(h_eci) - 1); h_eci[sizeof(h_eci) - 1] = 0;

    /* ===== 2) 조회부 (매입 존재 + 기존 인증/검증 현황) =====
     * 매입 미존재(100)는 체인 신규건일 수 있어 정상 처리. */
    EXEC SQL SELECT count(*) INTO :h_pcnt FROM purchase WHERE purchase_id = :h_pid;
    if (sqlca.sqlcode < 0) {
        setl(b, T_RC, 8410L); Bchg(b, T_MSG, 0, "매입 조회 오류", 0L);
        userlog("[%s] 매입 조회 오류 [%d]", svcname, sqlca.sqlcode); FAIL(b);
    }
    if (h_pcnt == 0)
        userlog("[%s] 매입 미커밋/미존재 pid=%ld — 인증만 기록", svcname, h_pid);
    EXEC SQL SELECT count(*) INTO :h_prior FROM au_3ds WHERE purchase_id = :h_pid;
    if (sqlca.sqlcode < 0) { h_prior = 0; }
    EXEC SQL SELECT count(*) INTO :h_vcnt FROM au_verify WHERE purchase_id = :h_pid;
    if (sqlca.sqlcode < 0) { h_vcnt = 0; }
    if (h_prior > 0)
        userlog("[%s] 기존 3DS 인증 %ld건 존재 pid=%ld — 재인증 기록", svcname, h_prior, h_pid);

    /* ===== 3) ECI 판정 분기부 (auth_status / liability) ===== */
    if (strcmp(h_eci, "05") == 0) {
        strcpy(h_astat, "Y"); strcpy(h_liab, "ISSUER");  rc = 0;
    } else if (strcmp(h_eci, "06") == 0) {
        strcpy(h_astat, "A"); strcpy(h_liab, "ISSUER");  rc = 0;
    } else if (strcmp(h_eci, "07") == 0) {
        strcpy(h_astat, "N"); strcpy(h_liab, "MERCHANT"); rc = 2;
        userlog("[%s] 미인증(ECI07) — 책임 가맹점 pid=%ld", svcname, h_pid);
    } else {
        strcpy(h_astat, "U"); strcpy(h_liab, "MERCHANT"); rc = 1;
        userlog("[%s] 미지원 ECI=[%s] — 불가(U)/가맹점 pid=%ld", svcname, h_eci, h_pid);
    }

    /* ===== 4) 본처리부 (au_3ds 채번·INSERT) ===== */
    EXEC SQL SELECT nextval('au_3ds_seq') INTO :h_tds;
    if (sqlca.sqlcode < 0) {
        setl(b, T_RC, 8420L); Bchg(b, T_MSG, 0, "3DS 시퀀스 채번 실패", 0L);
        userlog("[%s] 시퀀스 채번 실패 [%d]", svcname, sqlca.sqlcode); FAIL(b);
    }
    EXEC SQL INSERT INTO au_3ds
        (tds_id, purchase_id, version, eci, auth_status, liability)
        VALUES (:h_tds, :h_pid, :h_ver, :h_eci, :h_astat, :h_liab);
    if (sqlca.sqlcode < 0) {
        setl(b, T_RC, 8421L); Bchg(b, T_MSG, 0, "3DS 인증결과 적재 실패", 0L);
        userlog("[%s] au_3ds 적재 실패 [%d]", svcname, sqlca.sqlcode); FAIL(b);
    }

    /* ===== 5) 적재 재검증부 (기록행 재조회) ===== */
    EXEC SQL SELECT auth_status, liability INTO :h_astat, :h_liab
        FROM au_3ds WHERE tds_id = :h_tds;
    if (sqlca.sqlcode < 0 || sqlca.sqlcode == 100) {
        setl(b, T_RC, 8430L); Bchg(b, T_MSG, 0, "3DS 적재 재검증 실패", 0L);
        userlog("[%s] 재검증 실패 tds=%ld code=%d", svcname, h_tds, sqlca.sqlcode); FAIL(b);
    }

    /* ===== 6) 응답부 ===== */
    Bchg(b, T_STATUS, 0, h_astat, 0L);   /* auth_status: Y/A/N/U */
    Bchg(b, T_STR2, 0, h_liab, 0L);      /* liability: ISSUER/MERCHANT */
    setl(b, T_ID1, h_tds);
    setl(b, T_RC, rc);
    Bchg(b, T_MSG, 0,
         (strcmp(h_liab, "ISSUER") == 0 ? "3DS 인증 완료(책임전환)" : "3DS 미전환(가맹점 책임)"),
         0L);

    /* ===== 7) 완료 로깅 ===== */
    userlog("[%s] 완료: pid=%ld eci=%s status=%s liability=%s tds=%ld rc=%ld",
            svcname, h_pid, h_eci, h_astat, h_liab, h_tds, rc);
    OK(b);
}

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