/*
 * ACQ_DISPUTE_ADVANCE.pgc - ac 모듈 서비스 ACQ_DISPUTE_ADVANCE (one service = one file).
 *
 * 분쟁 라이프사이클 상태기계. 카드 분쟁은 정해진 순서로만 진행하며, 이 서비스는
 * 현재 stage/status 를 읽어 요청 action 에 대한 "적법한 전이만" 허용하고 나머지는 거부한다.
 *
 *   stage/action 전이표 (status='OPEN' 인 열린 분쟁에서만):
 *     FIRST_CB    --REPRESENT--> REPRESENT        (매입사 재청구 방어)
 *     REPRESENT   --ESCALATE---> PRE_ARB          (사전 중재 상신)
 *     PRE_ARB     --ESCALATE---> ARBITRATION      (중재 상신)
 *     ARBITRATION --WIN--------> status=WON  (종결, resolved_at)
 *     ARBITRATION --LOSE-------> status=LOST (종결, resolved_at)
 *     <any open>  --ACCEPT-----> status=ACCEPTED  (책임 인수, 종결)
 *   그 외 (stage,action) 조합 = 부적절한 전이 → T_RC 세팅 후 FAIL.
 *   이미 WON/LOST/ACCEPTED 로 종결된 분쟁은 어떤 전이도 거부.
 *
 * 입출력 계약: 입력 T_ID1(dispute_id) + T_STR1(action)[+ T_STR2(현재 stage 힌트)],
 *             출력 T_STATUS(새 stage 또는 종결 status).
 * Runs on the caller's XA branch (no EXEC SQL CONNECT). Advertised by ac_svr.
 */
#include "ACQ_DISPUTE_ADVANCE.h"

void ACQ_DISPUTE_ADVANCE(TPSVCINFO *p)
{
    UBFH *b = (UBFH *)p->data;
    const char *SVC = "ACQ_DISPUTE_ADVANCE";
    char action[24], bizdate[16], newstage[16], newstatus[16], memo[256], logmsg[256];
    long resolve = 0, valid = 0, i = 0;
    EXEC SQL BEGIN DECLARE SECTION;
    long h_did, h_pid, h_amt, h_logid, h_open;
    char h_stage[16], h_status[16], h_merch[64], h_reason[64];
    char h_new_stage[16], h_new_status[16], h_bizdate[16], h_memo[256], h_logmsg[256];
    EXEC SQL END DECLARE SECTION;

    /* 지역/호스트 변수 초기화 (DECLARE SECTION 밖) */
    h_did = h_pid = h_amt = h_logid = h_open = 0;
    action[0] = bizdate[0] = newstage[0] = newstatus[0] = memo[0] = logmsg[0] = 0;
    h_stage[0] = h_status[0] = h_reason[0] = h_bizdate[0] = 0;
    strcpy(h_merch, "UNKNOWN");
    userlog("%s 진입: 분쟁 단계 전이 요청", SVC);

    /* [1] 입력 검증부 -------------------------------------------------- */
    h_did = getl(b, T_ID1);
    if (h_did <= 0) {
        Bchg(b, T_MSG, 0, "분쟁 ID(T_ID1) 오류", 0L); setl(b, T_RC, 7301); FAIL(b);
    }
    gets_(b, T_STR1, action, sizeof(action));
    if (action[0] == 0) {
        Bchg(b, T_MSG, 0, "action(T_STR1) 필수", 0L); setl(b, T_RC, 7302); FAIL(b);
    }
    for (i = 0; action[i]; i++)                         /* action 대문자 정규화 */
        if (action[i] >= 'a' && action[i] <= 'z') action[i] -= 32;
    gets_(b, T_BIZDATE, bizdate, sizeof(bizdate));
    strncpy(h_bizdate, bizdate, sizeof(h_bizdate)-1); h_bizdate[sizeof(h_bizdate)-1] = 0;
    if (h_bizdate[0] == 0) {
        EXEC SQL SELECT param_val INTO :h_bizdate FROM cm_param WHERE param_key = 'BIZ_DATE';
        if (sqlca.sqlcode != 0) strcpy(h_bizdate, "2026-07-19");
    }

    /* [2] 마스터 조회부: 현재 분쟁 상태 (전이의 기준) ------------------- */
    EXEC SQL SELECT purchase_id, merchant_id, amount, reason_code, stage, status
        INTO :h_pid, :h_merch, :h_amt, :h_reason, :h_stage, :h_status
        FROM ac_dispute WHERE dispute_id = :h_did;
    if (sqlca.sqlcode < 0) {
        userlog("%s: 분쟁 조회 실패 [%d] %s", SVC, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        setl(b, T_RC, 90); FAIL(b);
    }
    if (sqlca.sqlcode == 100) {
        /* XA 격리: 형제 브랜치가 방금 개시한 미커밋 분쟁이면 전문에 실린 현재 stage 를 쓴다.
         * 전문 힌트(T_STR2)도 없으면 진짜 미존재이므로 업무검증 실패로 거부한다. */
        gets_(b, T_STR2, h_stage, sizeof(h_stage));
        gets_(b, T_STATUS, h_status, sizeof(h_status));
        if (h_status[0] == 0) strcpy(h_status, "OPEN");
        h_pid = getl(b, T_PURCHASE_ID);
        h_amt = getl(b, T_AMOUNT);
        if (h_stage[0] == 0) {
            userlog("%s: 분쟁 미존재 did=%ld (전문 힌트 없음)", SVC, h_did);
            Bchg(b, T_MSG, 0, "분쟁 미존재", 0L); setl(b, T_RC, 7303); FAIL(b);
        }
        userlog("%s: 분쟁 미커밋(체인) did=%ld — 전문 stage=%s 사용", SVC, h_did, h_stage);
    }
    userlog("%s 컨텍스트: did=%ld pid=%ld merch=%s stage=%s status=%s action=%s",
            SVC, h_did, h_pid, h_merch, h_stage, h_status, action);

    /* [3] 종결 상태 확인부: 이미 resolved 면 어떤 전이도 불가 ----------- */
    if (strcmp(h_status, "WON") == 0 || strcmp(h_status, "LOST") == 0 ||
        strcmp(h_status, "ACCEPTED") == 0) {
        snprintf(logmsg, sizeof(logmsg), "이미 종결된 분쟁 status=%s 전이 거부", h_status);
        userlog("%s %s did=%ld", SVC, logmsg, h_did);
        Bchg(b, T_MSG, 0, logmsg, 0L);
        Bchg(b, T_STATUS, 0, h_status, 0L);
        setl(b, T_RC, 7310); FAIL(b);
    }

    /* [4] 상태기계 전이 판정부 ----------------------------------------- */
    strcpy(newstage, h_stage); strcpy(newstatus, h_status);
    resolve = 0; valid = 0;
    if (strcmp(action, "ACCEPT") == 0) {
        /* 어느 열린 단계에서든 가맹점/매입사가 책임을 인수 → ACCEPTED(종결) */
        strcpy(newstatus, "ACCEPTED"); resolve = 1; valid = 1;
    } else if (strcmp(h_stage, "FIRST_CB") == 0 && strcmp(action, "REPRESENT") == 0) {
        strcpy(newstage, "REPRESENT"); valid = 1;
    } else if (strcmp(h_stage, "REPRESENT") == 0 && strcmp(action, "ESCALATE") == 0) {
        strcpy(newstage, "PRE_ARB"); valid = 1;
    } else if (strcmp(h_stage, "PRE_ARB") == 0 && strcmp(action, "ESCALATE") == 0) {
        strcpy(newstage, "ARBITRATION"); valid = 1;
    } else if (strcmp(h_stage, "ARBITRATION") == 0 &&
               (strcmp(action, "WIN") == 0 || strcmp(action, "WON") == 0)) {
        strcpy(newstatus, "WON"); resolve = 1; valid = 1;
    } else if (strcmp(h_stage, "ARBITRATION") == 0 &&
               (strcmp(action, "LOSE") == 0 || strcmp(action, "LOSS") == 0 ||
                strcmp(action, "LOST") == 0)) {
        strcpy(newstatus, "LOST"); resolve = 1; valid = 1;
    }
    if (!valid) {
        snprintf(logmsg, sizeof(logmsg), "부적절한 전이 거부: stage=%s action=%s", h_stage, action);
        userlog("%s %s did=%ld", SVC, logmsg, h_did);
        Bchg(b, T_MSG, 0, logmsg, 0L);
        Bchg(b, T_STATUS, 0, h_stage, 0L);   /* 현재 stage 유지 통지 */
        setl(b, T_RC, 7320); FAIL(b);
    }
    userlog("%s 전이확정: %s/%s --%s--> stage=%s status=%s resolve=%ld",
            SVC, h_stage, h_status, action, newstage, newstatus, resolve);

    /* [5] 본처리부: ac_dispute UPDATE (종결 전이면 resolved_at 세팅) ----- */
    strncpy(h_new_stage, newstage, sizeof(h_new_stage)-1); h_new_stage[sizeof(h_new_stage)-1] = 0;
    strncpy(h_new_status, newstatus, sizeof(h_new_status)-1); h_new_status[sizeof(h_new_status)-1] = 0;
    snprintf(memo, sizeof(memo), "전이 %s/%s -%s-> %s/%s @%s",
             h_stage, h_status, action, h_new_stage, h_new_status, h_bizdate);
    strncpy(h_memo, memo, sizeof(h_memo)-1); h_memo[sizeof(h_memo)-1] = 0;
    if (resolve) {
        EXEC SQL UPDATE ac_dispute
            SET stage = :h_new_stage, status = :h_new_status, resolved_at = now(), memo = :h_memo
            WHERE dispute_id = :h_did;
    } else {
        EXEC SQL UPDATE ac_dispute
            SET stage = :h_new_stage, status = :h_new_status, memo = :h_memo
            WHERE dispute_id = :h_did;
    }
    if (sqlca.sqlcode < 0) {
        userlog("%s: 분쟁 갱신 실패 [%d] %s", SVC, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
        setl(b, T_RC, 90); FAIL(b);
    }
    if (sqlca.sqlcode == 100) {
        /* XA 격리: 대상 행이 이 브랜치에 안 보임(체인 미커밋). 전문 기반으로 진행하고 FAIL 안 함 */
        userlog("%s: UPDATE 대상 미가시(체인 미커밋) did=%ld — 전문값 응답", SVC, h_did);
    }

    /* [6] 이력/감사 적재부 (cm_log) ------------------------------------- */
    snprintf(logmsg, sizeof(logmsg), "분쟁전이 did=%ld %s->%s/%s action=%s resolve=%ld",
             h_did, h_stage, h_new_stage, h_new_status, action, resolve);
    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_DISPUTE_ADVANCE', 'I', :h_logmsg, :h_bizdate);
    if (sqlca.sqlcode < 0) { setl(b, T_RC, 90); FAIL(b); }

    /* [7] 집계/요약부: 가맹점 진행중 분쟁 수 재집계 --------------------- */
    EXEC SQL SELECT count(*) INTO :h_open FROM ac_dispute
        WHERE merchant_id = :h_merch AND status = 'OPEN';
    if (sqlca.sqlcode < 0) { h_open = 0; }   /* 집계 실패는 응답을 막지 않음 */

    /* [8] 응답부 (계약 보존: T_STATUS = 새 stage 또는 종결 status) ------- */
    if (resolve) Bchg(b, T_STATUS, 0, h_new_status, 0L);
    else         Bchg(b, T_STATUS, 0, h_new_stage, 0L);
    setl(b, T_ID1, h_did);
    setl(b, T_PURCHASE_ID, h_pid);
    setl(b, T_AMOUNT, h_amt);
    Bchg(b, T_MERCHANT, 0, h_merch, 0L);
    Bchg(b, T_STR2, 0, h_new_stage, 0L);     /* 새 stage 힌트(체인 전달용) */
    Bchg(b, T_STR1, 0, action, 0L);
    setl(b, T_ARG1, resolve);
    setl(b, T_COUNT, h_open);
    Bchg(b, T_MSG, 0, h_memo, 0L);
    setl(b, T_RC, 0);
    userlog("%s 완료: did=%ld -> stage=%s status=%s (resolve=%ld)",
            SVC, h_did, h_new_stage, h_new_status, resolve);
    OK(b);
}

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