#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────────────
# erp_module 포괄 생애주기 E2E — 설정부터 안치단 조회까지 전 체인 (실제 HTTP + DB)
#
#   카테고리 → 부모 자리타입(관리비/정상가) → 자리(spot) → 배치도 셀(grid)
#   → 자리별 전용타입(자식, 독립) → niche(안치단) 페이지 렌더 → 전체 정리
#
#   각 단계는 실제 로그인 세션으로 API 를 호출하고 DB 저장을 직접 확인한다.
#   ⚠ 테스트가 만든 카테고리/자리/셀/타입/계정은 종료 시 FK 순서대로 자동 삭제.
#   사용:  bash bin/e2e_full_lifecycle.sh
# ─────────────────────────────────────────────────────────────────────────────
set -uo pipefail
ROOT="/home/erp_module/www"; DB="erp_module"; HOST="erp_module.acux.store"; BASE="http://127.0.0.1"
JAR="$(mktemp)"; TMP="$(mktemp -d)"
QA_USER="qa_lc_$$"; QA_PW="QaLc!$$secret"; TAG="_LC$$"
QA_ACC_ID=""; CAT_ID=""; PARENT_TYPE_ID=""; SPOT_ID=""; CHILD_TYPE_ID=""

PASS=0; FAIL=0
ok(){ printf '  \033[32m✓ PASS\033[0m  %s\n' "$1"; PASS=$((PASS+1)); }
bad(){ printf '  \033[31m✗ FAIL\033[0m  %s\n' "$1"; FAIL=$((FAIL+1)); }
stage(){ printf '\n\033[1m━━ %s\033[0m\n' "$1"; }
mq(){ mysql -N -u root "$DB" -e "$1" 2>/dev/null; }
curlh(){ curl -s -H "Host: $HOST" -c "$JAR" -b "$JAR" "$@"; }

cleanup(){
  stage "정리 (FK 순서대로 삭제)"
  [ -n "$SPOT_ID" ]        && { mq "DELETE FROM burial_spot_cells WHERE spot_id=$SPOT_ID"; echo "  - 셀(spot $SPOT_ID) 삭제"; }
  [ -n "$SPOT_ID" ]        && { mq "DELETE FROM burial_spot_custom_types WHERE spot_id=$SPOT_ID"; echo "  - 자식타입(spot $SPOT_ID) 삭제"; }
  [ -n "$SPOT_ID" ]        && { mq "DELETE FROM burial_spots WHERE id=$SPOT_ID"; echo "  - 자리 #$SPOT_ID 삭제"; }
  [ -n "$CAT_ID" ]         && { mq "DELETE FROM burial_category_spot_types WHERE category_id=$CAT_ID"; echo "  - 부모타입(cat $CAT_ID, 미지정 포함) 삭제"; }
  [ -n "$CAT_ID" ]         && { mq "DELETE FROM burial_categories WHERE id=$CAT_ID"; echo "  - 카테고리 #$CAT_ID 삭제"; }
  [ -n "$QA_ACC_ID" ]      && { mq "DELETE FROM accounts WHERE id=$QA_ACC_ID"; echo "  - 임시 계정 #$QA_ACC_ID 삭제"; }
  rm -rf "$JAR" "$TMP"
}
trap cleanup EXIT

# ── 0) 임시 master 계정 + 로그인 ────────────────────────────────────────────
stage "STEP 0 · 임시 master 계정 + HTTP 로그인"
HASH=$(php -r 'echo password_hash($argv[1], PASSWORD_DEFAULT);' "$QA_PW")
mq "INSERT INTO accounts (user_id,user_password,name,roles_id,is_active,created_at) VALUES ('$QA_USER','$HASH','QA LC',1,1,NOW())"
QA_ACC_ID=$(mq "SELECT id FROM accounts WHERE user_id='$QA_USER' LIMIT 1")
[ -n "$QA_ACC_ID" ] && ok "임시 master 계정 (#$QA_ACC_ID)" || { bad "계정 생성 실패"; exit 1; }
curlh "$BASE/login" > "$TMP/login.html"
FORM_CSRF=$(grep -o 'name="_csrf_token" value="[^"]*"' "$TMP/login.html" | head -1 | sed 's/.*value="\([^"]*\)".*/\1/')
curlh -o /dev/null --data-urlencode "mb_id=$QA_USER" --data-urlencode "mb_password=$QA_PW" --data-urlencode "_csrf_token=$FORM_CSRF" "$BASE/admin/index.php"
curlh "$BASE/setup-map-basic" > "$TMP/basic.html"
CSRF=$(grep -o '<meta name="csrf-token" content="[^"]*"' "$TMP/basic.html" | head -1 | sed 's/.*content="\([^"]*\)".*/\1/')
[ -n "$CSRF" ] && ok "로그인 + CSRF 토큰 확보" || { bad "로그인/CSRF 실패"; exit 1; }
apipost(){ curlh -H "Content-Type: application/json" -H "X-CSRF-TOKEN: $CSRF" -X POST --data "$2" "$BASE$1"; }

# ── 1) [WRITE] 카테고리 생성 ────────────────────────────────────────────────
stage "STEP 1 · [WRITE] 카테고리 생성 (안치단 type)"
R=$(apipost "/setting/api/burial_categories.php" "{\"name\":\"$TAG카테고리\",\"spot_type\":\"ossuary\",\"description\":\"E2E\",\"sort_order\":99,\"is_active\":1}")
echo "$R" | grep -q '"success":true' && ok "카테고리 생성 API 성공" || bad "카테고리 생성 실패: $(echo "$R"|head -c160)"
CAT_ID=$(mq "SELECT id FROM burial_categories WHERE name='$TAG카테고리' LIMIT 1")
[ -n "$CAT_ID" ] && ok "DB 확인: 카테고리 #$CAT_ID 저장됨" || bad "카테고리 DB 미저장"
MIJI=$(mq "SELECT COUNT(*) FROM burial_category_spot_types WHERE category_id=$CAT_ID AND name='미지정'")
[ "$MIJI" = "1" ] && ok "기본 '미지정' 자리타입 자동 생성 확인" || bad "'미지정' 타입 자동생성 안 됨 ($MIJI)"

# ── 2) [WRITE] 부모 자리타입 (관리비 + 정상가) ──────────────────────────────
stage "STEP 2 · [WRITE] 부모 자리타입 생성 (관리비/정상가)"
R=$(apipost "/setting/api/burial_category_spot_types.php" "{\"category_id\":$CAT_ID,\"name\":\"$TAG타입\",\"cols\":1,\"capacity\":1,\"is_communal\":0,\"maintenance_fee\":5000,\"list_price\":10000000,\"bg_color\":\"#dbeafe\",\"border_color\":\"#93c5fd\",\"sort_order\":1}")
echo "$R" | grep -q '"success":true' && ok "부모 타입 생성 성공" || bad "부모 타입 실패: $(echo "$R"|head -c160)"
PARENT_TYPE_ID=$(mq "SELECT id FROM burial_category_spot_types WHERE category_id=$CAT_ID AND name='$TAG타입' AND deleted_at IS NULL LIMIT 1")
PROW=$(mq "SELECT CONCAT(maintenance_fee,'/',list_price) FROM burial_category_spot_types WHERE id=$PARENT_TYPE_ID")
[ "$PROW" = "5000/10000000" ] && ok "DB 확인: 부모 관리비/정상가 = $PROW" || bad "부모 값 불일치: $PROW"

# ── 3) [WRITE] 자리(spot) 생성 ──────────────────────────────────────────────
stage "STEP 3 · [WRITE] 자리(spot) 생성"
R=$(apipost "/setting/api/burial_spots.php" "{\"category_id\":$CAT_ID,\"spot_no\":\"$TAG자리\",\"spot_label\":\"E2E자리\",\"status\":\"available\",\"memo\":\"\"}")
echo "$R" | grep -q '"success":true' && ok "자리 생성 성공" || bad "자리 생성 실패: $(echo "$R"|head -c160)"
SPOT_ID=$(mq "SELECT id FROM burial_spots WHERE category_id=$CAT_ID AND spot_no='$TAG자리' AND deleted_at IS NULL LIMIT 1")
[ -n "$SPOT_ID" ] && ok "DB 확인: 자리 #$SPOT_ID 저장됨" || bad "자리 DB 미저장"

# ── 4) [WRITE] 배치도 셀(grid) 저장 — 2x2, 부모타입으로 채움 ────────────────
stage "STEP 4 · [WRITE] 배치도 셀 저장 (2×2 그리드)"
PK="st_$PARENT_TYPE_ID"
GRID="{\"sections\":[{\"name\":\"\",\"rows\":2,\"cols\":2,\"cells\":[[{\"type\":\"$PK\",\"label\":\"101\"},{\"type\":\"$PK\",\"label\":\"102\"}],[{\"type\":\"$PK\",\"label\":\"201\"},{\"type\":\"$PK\",\"label\":\"202\"}]]}]}"
R=$(apipost "/setting/api/burial_spot_cells.php" "{\"action\":\"save_grid\",\"spot_id\":$SPOT_ID,\"grid_data\":$GRID}")
echo "$R" | grep -q '"success":true' && ok "배치도 저장 성공" || bad "배치도 저장 실패: $(echo "$R"|head -c200)"
NCELL=$(mq "SELECT COUNT(*) FROM burial_spot_cells WHERE spot_id=$SPOT_ID AND cell_type='$PK'")
[ "$NCELL" = "4" ] && ok "DB 확인: 셀 4개 저장됨 (cell_type=$PK)" || bad "셀 개수 불일치: $NCELL (기대 4)"

# ── 5) [WRITE] 자리별 전용타입(자식) localize → 독립성 ──────────────────────
stage "STEP 5 · [WRITE] 자리 전용타입(자식) 생성 → 독립 확인"
R=$(apipost "/setting/api/burial_spot_custom_types.php" "{\"spot_id\":$SPOT_ID,\"source_type_id\":$PARENT_TYPE_ID,\"name\":\"$TAG자식\",\"cols\":1,\"capacity\":1,\"is_communal\":0,\"maintenance_fee\":7777,\"list_price\":9999999,\"bg_color\":\"#dbeafe\",\"border_color\":\"#93c5fd\",\"sort_order\":1,\"replace_source\":false}")
echo "$R" | grep -q '"success":true' && ok "자식 타입 생성 성공" || bad "자식 생성 실패: $(echo "$R"|head -c160)"
CHILD_TYPE_ID=$(mq "SELECT id FROM burial_spot_custom_types WHERE spot_id=$SPOT_ID AND name='$TAG자식' AND deleted_at IS NULL LIMIT 1")
CROW=$(mq "SELECT CONCAT(maintenance_fee,'/',list_price) FROM burial_spot_custom_types WHERE id=$CHILD_TYPE_ID")
PROW2=$(mq "SELECT CONCAT(maintenance_fee,'/',list_price) FROM burial_category_spot_types WHERE id=$PARENT_TYPE_ID")
[ "$CROW" = "7777/9999999" ] && ok "DB 확인: 자식 전용값 = $CROW" || bad "자식 값 불일치: $CROW"
[ "$PROW2" = "5000/10000000" ] && ok "독립성: 자식 생성 후에도 부모 = $PROW2 그대로" || bad "독립성 위반: 부모 $PROW2"

# ── 6) [READ] niche 안치단 페이지 렌더 ──────────────────────────────────────
stage "STEP 6 · [READ] 안치단(niche) 페이지 렌더 — type=$CAT_ID"
NICHE=$(curlh -w '\n__CODE__%{http_code}' "$BASE/niche?type=$CAT_ID")
NCODE=$(echo "$NICHE" | sed -n 's/.*__CODE__//p')
NBODY=$(echo "$NICHE" | sed 's/__CODE__.*//')
[ "$NCODE" = "200" ] && ok "niche 페이지 HTTP 200" || bad "niche 페이지 HTTP $NCODE"
# niche 는 자리 선택 라디오를 id="spot_<자리id>" 로 렌더 (라벨 텍스트는 spot_label 사용)
echo "$NBODY" | grep -q "id=\"spot_$SPOT_ID\"" && ok "niche 페이지에 생성한 자리(#$SPOT_ID) 라디오 노출" || bad "niche 페이지에 자리 라디오 미노출"
# 셀 번호(101)가 렌더되는지 — 카테고리→자리→배치도 셀→페이지 연결 확인
echo "$NBODY" | grep -q "101" && ok "niche 페이지에 셀 번호(101) 렌더 — 배치도 연결 정상" || bad "셀 번호 미렌더 — 배치도 연결 끊김"

# ── 7) [READ] 전체 체인 정합성 (DB 조인) ────────────────────────────────────
stage "STEP 7 · [READ] 전체 체인 DB 정합성"
CHAIN=$(mq "SELECT COUNT(*) FROM burial_categories cat
  JOIN burial_spots s ON s.category_id=cat.id AND s.deleted_at IS NULL
  JOIN burial_spot_cells c ON c.spot_id=s.id
  WHERE cat.id=$CAT_ID")
[ "${CHAIN:-0}" -ge 4 ] && ok "카테고리→자리→셀 조인 $CHAIN건 정합" || bad "체인 조인 불일치: $CHAIN"

printf '\n\033[1m━━ 포괄 E2E 결과\033[0m\n  통과 %d · 실패 %d\n' "$PASS" "$FAIL"
[ "$FAIL" -eq 0 ] && printf '  \033[32m전체 통과 — 설정부터 안치단 조회까지 전 체인 검증\033[0m\n' || printf '  \033[31m실패 확인 필요\033[0m\n'
[ "$FAIL" -eq 0 ]
