#!/bin/bash
##
## build.sh - REUSABLE build + Enduro/X config generator for acquire-core-x.
##
## Discovers every module under app/src/<mod>/, ecpg-precompiles its .pgc, builds
##   - libacqcommon.a           (from app/src/common/*.c)          [once]
##   - lib<mod>dbio.a           (from app/src/<mod>/dbio/*.pgc)     [per module]
##   - <mod>_svr                (from app/src/<mod>/<mod>_svr.pgc)  [per module]
##   - <mod> batches            (from app/src/<mod>/batch/*.pgc)    [per module]
##   - standalone clients       (from app/src/clients/*.c)
## then GENERATES app/conf/ndrxconfig.xml with one <server> entry per <mod>_svr.
##
## Adding a new module later = drop app/src/<mod>/{<mod>_svr.pgc,dbio,batch} and
## re-run build.sh. No hand-editing of config or this script is required: modules,
## servers, dbio libs, batches, and srvids are all DISCOVERED.
##
set -euo pipefail

# App root = this script's own directory (normally /app in the container, but
# relocatable so an isolated copy — e.g. CI building a throwaway /b — works too).
APP="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SRC=$APP/src
BIN=$APP/bin
LIB=$APP/lib
OBJ=$APP/obj
UBF=$APP/ubftab
CONF=$APP/conf
EXINC=/usr/local/include
PGINC="$(pg_config --includedir)"
PGLIB="$(pg_config --libdir)"

mkdir -p "$BIN" "$LIB" "$OBJ"

# Includes for every compile (CFLAGS is honored by buildserver/buildclient and
# by our direct gcc calls). Add every module's dbio AND svc dir so headers resolve
# (svc/*.pgc copybooks include the module's dbio + common headers).
CFLAGS="-I$UBF -I$EXINC -I$PGINC -I$SRC/common"
for d in "$SRC"/*/dbio; do [ -d "$d" ] && CFLAGS="$CFLAGS -I$d"; done
for d in "$SRC"/*/svc;  do [ -d "$d" ] && CFLAGS="$CFLAGS -I$d"; done
export CFLAGS
PGLINK="-L$PGLIB -lecpg -lpq"

# ecpg needs the same header search path as gcc (its preprocessor opens the
# #include'd copybooks to find EXEC SQL host-var decls). Mirror CFLAGS' -I set.
ECPG_INC="-I$UBF -I$SRC/common"
for d in "$SRC"/*/dbio; do [ -d "$d" ] && ECPG_INC="$ECPG_INC -I$d"; done
for d in "$SRC"/*/svc;  do [ -d "$d" ] && ECPG_INC="$ECPG_INC -I$d"; done

log() { echo "[build] $*"; }

# ---------------------------------------------------------------------------
# discover modules = dirs app/src/<mod>/ that contain <mod>_svr.pgc
# ---------------------------------------------------------------------------
MODS=()
for d in "$SRC"/*/; do
    m="$(basename "$d")"
    [ -f "$d/${m}_svr.pgc" ] && MODS+=("$m")
done
IFS=$'\n' MODS=($(printf '%s\n' "${MODS[@]}" | sort)); unset IFS
log "modules discovered: ${MODS[*]}"

# ---------------------------------------------------------------------------
# 0. UBF field header
# ---------------------------------------------------------------------------
log "mkfldhdr acq.fd"
( cd "$UBF" && FIELDTBLS=acq.fd FLDTBLDIR="$UBF" mkfldhdr acq.fd >/dev/null )

# ecpg precompile helper: $1 = .pgc path -> echoes generated .c path
ecpg_gen() {
    local pgc="$1" base out
    base="$(basename "${pgc%.pgc}")"
    out="$OBJ/${base}.c"
    ecpg $ECPG_INC -I"$(dirname "$pgc")" -o "$out" "$pgc"
    echo "$out"
}

# ---------------------------------------------------------------------------
# 1. common lib -> libacqcommon.a
# ---------------------------------------------------------------------------
log "libacqcommon.a"
COMMON_OBJS=()
for c in "$SRC"/common/*.c; do
    o="$OBJ/$(basename "${c%.c}").o"
    gcc -c $CFLAGS "$c" -o "$o"
    COMMON_OBJS+=("$o")
done
ar rcs "$LIB/libacqcommon.a" "${COMMON_OBJS[@]}"
NSVR=0; NDBIO=0; NBATCH=0

# ---------------------------------------------------------------------------
# 2..4 per module: dbio lib, server, batches
# ---------------------------------------------------------------------------
NSVC=0
for m in "${MODS[@]}"; do
    MDIR="$SRC/$m"
    DBIO_LIB=""
    SVC_LIB=""

    # -- dbio static lib (optional) --
    if compgen -G "$MDIR/dbio/*.pgc" >/dev/null; then
        log "lib${m}dbio.a"
        DB_OBJS=()
        for pgc in "$MDIR"/dbio/*.pgc; do
            c="$(ecpg_gen "$pgc")"
            o="${c%.c}.o"
            gcc -c $CFLAGS "$c" -o "$o"
            DB_OBJS+=("$o")
        done
        ar rcs "$LIB/lib${m}dbio.a" "${DB_OBJS[@]}"
        DBIO_LIB="$LIB/lib${m}dbio.a"
        NDBIO=$((NDBIO+1))
    fi

    # -- per-service static lib (NEW legacy layout, optional) --
    # A module may keep its services INLINE in <mod>_svr.pgc (old style) OR split
    # them into svc/*.pgc, one service per file (new style). Both are supported;
    # when svc/*.pgc exist they are archived into lib<mod>svc.a and linked in.
    if compgen -G "$MDIR/svc/*.pgc" >/dev/null; then
        log "lib${m}svc.a"
        SVC_OBJS=()
        for pgc in "$MDIR"/svc/*.pgc; do
            c="$(ecpg_gen "$pgc")"
            o="${c%.c}.o"
            gcc -c $CFLAGS "$c" -o "$o"
            SVC_OBJS+=("$o")
        done
        ar rcs "$LIB/lib${m}svc.a" "${SVC_OBJS[@]}"
        SVC_LIB="$LIB/lib${m}svc.a"
        NSVC=$((NSVC+1))
    fi

    # -- module server <mod>_svr (links svc lib + dbio lib + common) --
    log "${m}_svr"
    SVR_C="$(ecpg_gen "$MDIR/${m}_svr.pgc")"
    buildserver -o "$BIN/${m}_svr" -f "$SVR_C" \
        -a "$SVC_LIB $DBIO_LIB $LIB/libacqcommon.a $PGLINK"
    NSVR=$((NSVR+1))

    # -- batches (optional): each *.pgc -> its own client executable --
    if compgen -G "$MDIR/batch/*.pgc" >/dev/null; then
        for pgc in "$MDIR"/batch/*.pgc; do
            name="$(basename "${pgc%.pgc}")"
            log "batch $name"
            BC="$(ecpg_gen "$pgc")"
            buildclient -o "$BIN/$name" -f "$BC" \
                -a "$DBIO_LIB $LIB/libacqcommon.a $PGLINK"
            NBATCH=$((NBATCH+1))
        done
    fi
done

# ---------------------------------------------------------------------------
# 5. standalone clients (plain C, no EXEC SQL)
# ---------------------------------------------------------------------------
NCLI=0
for c in "$SRC"/clients/*.c; do
    name="$(basename "${c%.c}")"
    log "client $name"
    # libacqcommon.a 링크: ISO 8583 코덱(acq_iso8583) 등 공통 C 함수 사용 가능.
    buildclient -o "$BIN/$name" -f "$c" -a "$LIB/libacqcommon.a -L$PGLIB -lpq"
    NCLI=$((NCLI+1))
done

# ---------------------------------------------------------------------------
# 6. GENERATE ndrxconfig.xml (tmsrv fixed at srvid 40; module servers 100 step 10)
# ---------------------------------------------------------------------------
log "generating ndrxconfig.xml for servers: ${MODS[*]/%/_svr}"
gen_servers() {
    local srvid=100
    for m in "${MODS[@]}"; do
        cat <<EOF
        <server name="${m}_svr">
            <srvid>${srvid}</srvid>
            <!-- 모듈 내부 tpcall 체인(예: SETTLE→ST_MDR)이 같은 서버로 되돌아오므로
                 복수 카피 필수. 카피가 1이면 호출자가 블록된 채 자기 요청을 못 꺼내
                 자기교착(TPETIME)이 난다. 모듈내 최대 체인 깊이 3 + 동시성 여유 = 4. -->
            <min>4</min>
            <max>4</max>
            <sysopt>-e \${NDRX_APPHOME}/log/${m}_svr.log -r</sysopt>
        </server>
EOF
        srvid=$((srvid+10))
    done
}
cat > "$CONF/ndrxconfig.xml" <<EOF
<?xml version="1.0" ?>
<!-- GENERATED by app/build.sh - do not hand-edit. One <server> per discovered
     <mod>_svr module server; each advertises its module's services at tpsvrinit. -->
<endurox>
    <appconfig>
        <sanity>1</sanity>
        <brrefresh>5</brrefresh>
        <restart_min>1</restart_min>
        <restart_step>1</restart_step>
        <restart_max>5</restart_max>
        <restart_to_check>20</restart_to_check>
        <gather_pq_stats>Y</gather_pq_stats>
    </appconfig>
    <defaults>
        <min>1</min>
        <max>1</max>
        <autokill>1</autokill>
        <start_max>20</start_max>
        <pingtime>100</pingtime>
        <ping_max>800</ping_max>
        <end_max>30</end_max>
        <killtime>1</killtime>
    </defaults>
    <servers>
        <!-- XA transaction manager for RM1 (ECPG/PostgreSQL). -->
        <server name="tmsrv">
            <srvid>40</srvid>
            <min>1</min>
            <max>1</max>
            <sysopt>-e \${NDRX_APPHOME}/log/tmsrv-rm1.log -r -- -t3 -l\${NDRX_APPHOME}/tmlogs/rm1 -m20</sysopt>
        </server>
$(gen_servers)
    </servers>
</endurox>
EOF

log "DONE: modules=${#MODS[@]} servers=$NSVR svc_libs=$NSVC dbio_libs=$NDBIO batches=$NBATCH clients=$NCLI"
echo "[build] server binaries: ${MODS[*]/%/_svr}"
