#!/usr/bin/env bash
# 로컬 CI 파이프라인 스크립트
# 7단계를 순서대로 실행하며 각 단계 결과를 추적합니다.

set -uo pipefail

WORKSPACE=/home/jay/workspace
TESTS_DIR=$WORKSPACE/tests
REQUIREMENTS=$WORKSPACE/requirements.txt
CI_LOG_FILE=$WORKSPACE/memory/logs/ci-latest.json

START_TIME=$(date +%s)
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S")

# ─────────────────────────────────────────────
# 단계별 결과 저장 변수
# ─────────────────────────────────────────────
STAGE_SYNTAX_STATUS="pass"
STAGE_SYNTAX_DETAIL=""
STAGE_PYTEST_STATUS="pass"
STAGE_PYTEST_DETAIL=""
STAGE_COVERAGE_STATUS="pass"
STAGE_COVERAGE_DETAIL=""
STAGE_PIP_AUDIT_STATUS="pass"
STAGE_PIP_AUDIT_DETAIL=""
STAGE_RUN_TESTS_STATUS="pass"
STAGE_RUN_TESTS_DETAIL=""
STAGE_HEALTH_CHECK_STATUS="pass"
STAGE_HEALTH_CHECK_DETAIL=""
STAGE_NPM_AUDIT_STATUS="pass"
STAGE_NPM_AUDIT_DETAIL=""

HAS_WARN=0
FINAL_EXIT=0

# stderr에만 로그 출력 (stdout은 JSON 전용)
log() {
    echo "$*" >&2
}

# ─────────────────────────────────────────────
# 1단계: 문법 검사 (py_compile)
# ─────────────────────────────────────────────
log "[CI] 1/7 문법 검사 시작..."

PY_FILES=()
while IFS= read -r -d '' f; do
    PY_FILES+=("$f")
done < <(find "$WORKSPACE" -name "*.py" -print0 2>/dev/null)

PY_FILE_COUNT=${#PY_FILES[@]}
SYNTAX_FAIL_FILE=""
SYNTAX_OK=1

for py_file in "${PY_FILES[@]}"; do
    if ! python3 -m py_compile "$py_file" 2>/dev/null; then
        SYNTAX_OK=0
        SYNTAX_FAIL_FILE="$py_file"
        log "[CI] 문법 오류 발견: $py_file"
        break
    fi
done

if [ "$SYNTAX_OK" -eq 0 ]; then
    STAGE_SYNTAX_STATUS="fail"
    STAGE_SYNTAX_DETAIL="syntax error in: $SYNTAX_FAIL_FILE"
    log "[CI] 1단계 실패 - 즉시 중단"
    FINAL_EXIT=1

    # 즉시 중단 전 JSON 출력
    END_TIME=$(date +%s)
    DURATION=$((END_TIME - START_TIME))

    SUMMARY=$(python3 -c "
import json
from datetime import datetime

result = {
    'timestamp': '$TIMESTAMP',
    'duration_seconds': $DURATION,
    'stages': {
        'syntax_check': {'status': '$STAGE_SYNTAX_STATUS', 'detail': '$STAGE_SYNTAX_DETAIL'},
        'pytest':        {'status': 'skip',                 'detail': 'skipped due to syntax failure'},
        'coverage':      {'status': 'skip',                 'detail': 'skipped due to syntax failure'},
        'pip_audit':     {'status': 'skip',                 'detail': 'skipped due to syntax failure'},
        'run_tests':     {'status': 'skip',                 'detail': 'skipped due to syntax failure'},
        'health_check':  {'status': 'skip',                 'detail': 'skipped due to syntax failure'},
        'npm_audit':     {'status': 'skip',                 'detail': 'skipped due to syntax failure'},
    },
    'verdict': 'FAIL',
    'exit_code': 1
}
print(json.dumps(result, ensure_ascii=False, indent=2))
")

    echo "$SUMMARY"
    mkdir -p "$(dirname "$CI_LOG_FILE")"
    echo "$SUMMARY" > "$CI_LOG_FILE"
    exit 1
fi

STAGE_SYNTAX_DETAIL="${PY_FILE_COUNT} files checked"
log "[CI] 1단계 완료 - $STAGE_SYNTAX_DETAIL"

# ─────────────────────────────────────────────
# 2단계: pytest 전체 실행
# ─────────────────────────────────────────────
log "[CI] 2/7 pytest 전체 실행 시작..."

PYTEST_OUTPUT=$(python3 -m pytest "$TESTS_DIR/" -v --tb=short 2>&1) || true
PYTEST_EXIT=$?

# 결과 파싱: "X passed" 추출
PYTEST_SUMMARY=$(echo "$PYTEST_OUTPUT" | grep -E "passed|failed|error" | tail -1 || true)

if [ $PYTEST_EXIT -ne 0 ]; then
    STAGE_PYTEST_STATUS="fail"
    STAGE_PYTEST_DETAIL="${PYTEST_SUMMARY:-exit code $PYTEST_EXIT}"
    log "[CI] 2단계 실패 - 즉시 중단"
    FINAL_EXIT=1

    END_TIME=$(date +%s)
    DURATION=$((END_TIME - START_TIME))

    # detail 내 따옴표 이스케이프
    SAFE_PYTEST_DETAIL=$(echo "$STAGE_PYTEST_DETAIL" | python3 -c "import sys; print(sys.stdin.read().strip().replace('\\\\','\\\\\\\\').replace('\"','\\\\\"'))")
    SAFE_SYNTAX_DETAIL=$(echo "$STAGE_SYNTAX_DETAIL" | python3 -c "import sys; print(sys.stdin.read().strip().replace('\\\\','\\\\\\\\').replace('\"','\\\\\"'))")

    SUMMARY=$(python3 -c "
import json

result = {
    'timestamp': '$TIMESTAMP',
    'duration_seconds': $DURATION,
    'stages': {
        'syntax_check': {'status': '$STAGE_SYNTAX_STATUS', 'detail': '$SAFE_SYNTAX_DETAIL'},
        'pytest':        {'status': '$STAGE_PYTEST_STATUS', 'detail': '$SAFE_PYTEST_DETAIL'},
        'coverage':      {'status': 'skip',                 'detail': 'skipped due to pytest failure'},
        'pip_audit':     {'status': 'skip',                 'detail': 'skipped due to pytest failure'},
        'run_tests':     {'status': 'skip',                 'detail': 'skipped due to pytest failure'},
        'health_check':  {'status': 'skip',                 'detail': 'skipped due to pytest failure'},
        'npm_audit':     {'status': 'skip',                 'detail': 'skipped due to pytest failure'},
    },
    'verdict': 'FAIL',
    'exit_code': 1
}
print(json.dumps(result, ensure_ascii=False, indent=2))
")

    echo "$SUMMARY"
    mkdir -p "$(dirname "$CI_LOG_FILE")"
    echo "$SUMMARY" > "$CI_LOG_FILE"
    exit 1
fi

STAGE_PYTEST_DETAIL="${PYTEST_SUMMARY:-all tests passed}"
log "[CI] 2단계 완료 - $STAGE_PYTEST_DETAIL"

# ─────────────────────────────────────────────
# 3단계: 커버리지 측정
# ─────────────────────────────────────────────
log "[CI] 3/7 커버리지 측정 시작..."

mkdir -p "$TESTS_DIR"
COVERAGE_OUTPUT=$(python3 -m pytest "$TESTS_DIR/" --cov="$WORKSPACE" --cov-report=term-missing 2>&1 | tee "$TESTS_DIR/coverage-report.txt") || true
COVERAGE_EXIT=$?

# "TOTAL ... XX%" 형태에서 커버리지 퍼센트 추출
COVERAGE_PCT=$(echo "$COVERAGE_OUTPUT" | grep -E "^TOTAL" | awk '{print $NF}' || true)

if [ $COVERAGE_EXIT -ne 0 ]; then
    STAGE_COVERAGE_STATUS="warn"
    STAGE_COVERAGE_DETAIL="coverage measurement failed (exit $COVERAGE_EXIT)"
    HAS_WARN=1
    log "[CI] 3단계 경고 - $STAGE_COVERAGE_DETAIL"
else
    STAGE_COVERAGE_DETAIL="coverage: ${COVERAGE_PCT:-unknown}"
    log "[CI] 3단계 완료 - $STAGE_COVERAGE_DETAIL"
fi

# ─────────────────────────────────────────────
# 4단계: pip-audit 의존성 검사
# ─────────────────────────────────────────────
log "[CI] 4/7 pip-audit 의존성 검사 시작..."

PIP_AUDIT_OUTPUT=$(pip-audit -r "$REQUIREMENTS" --disable-pip --no-deps 2>&1) || true
PIP_AUDIT_EXIT=$?

if [ $PIP_AUDIT_EXIT -ne 0 ]; then
    VULN_COUNT=$(echo "$PIP_AUDIT_OUTPUT" | grep -c "vulnerability\|VULN" 2>/dev/null || echo "1")
    STAGE_PIP_AUDIT_STATUS="warn"
    STAGE_PIP_AUDIT_DETAIL="${VULN_COUNT} vulnerability found"
    HAS_WARN=1
    log "[CI] 4단계 경고 - $STAGE_PIP_AUDIT_DETAIL"
else
    STAGE_PIP_AUDIT_DETAIL="no vulnerabilities found"
    log "[CI] 4단계 완료 - $STAGE_PIP_AUDIT_DETAIL"
fi

# ─────────────────────────────────────────────
# 5단계: 실행 테스트 (run_tests.py)
# ─────────────────────────────────────────────
log "[CI] 5/7 실행 테스트 시작..."

RUN_TESTS_OUTPUT=$(python3 "$TESTS_DIR/run_tests.py" 2>&1) || true
RUN_TESTS_EXIT=$?

# JSON 출력 파싱: failed > 0 이면 경고
RUN_TESTS_FAILED=$(echo "$RUN_TESTS_OUTPUT" | python3 -c "
import sys, json
try:
    data = json.loads(sys.stdin.read())
    print(data.get('failed', 0))
except Exception:
    print(-1)
" 2>/dev/null || echo "-1")

RUN_TESTS_PASSED=$(echo "$RUN_TESTS_OUTPUT" | python3 -c "
import sys, json
try:
    data = json.loads(sys.stdin.read())
    print(data.get('passed', 0))
except Exception:
    print(0)
" 2>/dev/null || echo "0")

if [ "$RUN_TESTS_FAILED" = "-1" ]; then
    # JSON 파싱 실패 - 실행 자체 오류
    if [ $RUN_TESTS_EXIT -ne 0 ]; then
        STAGE_RUN_TESTS_STATUS="warn"
        STAGE_RUN_TESTS_DETAIL="run_tests.py failed (exit $RUN_TESTS_EXIT)"
        HAS_WARN=1
        log "[CI] 5단계 경고 - $STAGE_RUN_TESTS_DETAIL"
    else
        STAGE_RUN_TESTS_DETAIL="completed (JSON parse error)"
        log "[CI] 5단계 완료 - $STAGE_RUN_TESTS_DETAIL"
    fi
elif [ "$RUN_TESTS_FAILED" -gt 0 ] 2>/dev/null; then
    STAGE_RUN_TESTS_STATUS="warn"
    STAGE_RUN_TESTS_DETAIL="${RUN_TESTS_PASSED} passed, ${RUN_TESTS_FAILED} failed"
    HAS_WARN=1
    log "[CI] 5단계 경고 - $STAGE_RUN_TESTS_DETAIL"
else
    STAGE_RUN_TESTS_DETAIL="${RUN_TESTS_PASSED} passed, 0 failed"
    log "[CI] 5단계 완료 - $STAGE_RUN_TESTS_DETAIL"
fi

# ─────────────────────────────────────────────
# 6단계: health-check
# ─────────────────────────────────────────────
log "[CI] 6/7 health-check 시작..."

HEALTH_OUTPUT=$(bash "$WORKSPACE/memory/health-check.sh" 2>/dev/null) || true

# JSON에서 summary.fail 추출
HEALTH_FAIL=$(echo "$HEALTH_OUTPUT" | python3 -c "
import sys, json
try:
    data = json.loads(sys.stdin.read())
    print(data.get('summary', {}).get('fail', 0))
except Exception:
    print(-1)
" 2>/dev/null || echo "-1")

HEALTH_PASS=$(echo "$HEALTH_OUTPUT" | python3 -c "
import sys, json
try:
    data = json.loads(sys.stdin.read())
    print(data.get('summary', {}).get('pass', 0))
except Exception:
    print(0)
" 2>/dev/null || echo "0")

if [ "$HEALTH_FAIL" = "-1" ]; then
    STAGE_HEALTH_CHECK_STATUS="warn"
    STAGE_HEALTH_CHECK_DETAIL="health-check output parse failed"
    HAS_WARN=1
    log "[CI] 6단계 경고 - $STAGE_HEALTH_CHECK_DETAIL"
elif [ "$HEALTH_FAIL" -gt 0 ] 2>/dev/null; then
    STAGE_HEALTH_CHECK_STATUS="warn"
    STAGE_HEALTH_CHECK_DETAIL="${HEALTH_FAIL} checks failed"
    HAS_WARN=1
    log "[CI] 6단계 경고 - $STAGE_HEALTH_CHECK_DETAIL"
else
    STAGE_HEALTH_CHECK_DETAIL="${HEALTH_PASS} checks passed"
    log "[CI] 6단계 완료 - $STAGE_HEALTH_CHECK_DETAIL"
fi

# ─────────────────────────────────────────────
# 7단계: npm audit
# ─────────────────────────────────────────────
log "[CI] 7/7 npm audit 시작..."

NPM_AUDIT_OUTPUT=$(bash "$WORKSPACE/scripts/npm-audit.sh" 2>&1) || true
NPM_AUDIT_EXIT=$?

if [ $NPM_AUDIT_EXIT -ne 0 ]; then
    STAGE_NPM_AUDIT_STATUS="warn"
    STAGE_NPM_AUDIT_DETAIL="HIGH+ vulnerabilities found"
    HAS_WARN=1
    log "[CI] 7단계 경고 - $STAGE_NPM_AUDIT_DETAIL"
else
    STAGE_NPM_AUDIT_DETAIL="no HIGH+ vulnerabilities"
    log "[CI] 7단계 완료 - $STAGE_NPM_AUDIT_DETAIL"
fi

# ─────────────────────────────────────────────
# 판정 및 JSON 서머리 생성
# ─────────────────────────────────────────────
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

if [ "$FINAL_EXIT" -ne 0 ]; then
    VERDICT="FAIL"
elif [ "$HAS_WARN" -gt 0 ]; then
    VERDICT="WARN"
else
    VERDICT="PASS"
fi

log "[CI] 전체 완료 - 판정: $VERDICT (소요시간: ${DURATION}초)"

# detail 문자열 내 특수문자 이스케이프 처리
safe_json_str() {
    echo "$1" | python3 -c "import sys; print(sys.stdin.read().strip().replace('\\\\','\\\\\\\\').replace('\"','\\\\\"').replace('\n',' '))"
}

S1=$(safe_json_str "$STAGE_SYNTAX_DETAIL")
S2=$(safe_json_str "$STAGE_PYTEST_DETAIL")
S3=$(safe_json_str "$STAGE_COVERAGE_DETAIL")
S4=$(safe_json_str "$STAGE_PIP_AUDIT_DETAIL")
S5=$(safe_json_str "$STAGE_RUN_TESTS_DETAIL")
S6=$(safe_json_str "$STAGE_HEALTH_CHECK_DETAIL")
S7=$(safe_json_str "$STAGE_NPM_AUDIT_DETAIL")

SUMMARY=$(python3 -c "
import json

result = {
    'timestamp': '$TIMESTAMP',
    'duration_seconds': $DURATION,
    'stages': {
        'syntax_check': {'status': '$STAGE_SYNTAX_STATUS',       'detail': '$S1'},
        'pytest':        {'status': '$STAGE_PYTEST_STATUS',       'detail': '$S2'},
        'coverage':      {'status': '$STAGE_COVERAGE_STATUS',     'detail': '$S3'},
        'pip_audit':     {'status': '$STAGE_PIP_AUDIT_STATUS',    'detail': '$S4'},
        'run_tests':     {'status': '$STAGE_RUN_TESTS_STATUS',    'detail': '$S5'},
        'health_check':  {'status': '$STAGE_HEALTH_CHECK_STATUS', 'detail': '$S6'},
        'npm_audit':     {'status': '$STAGE_NPM_AUDIT_STATUS',    'detail': '$S7'},
    },
    'verdict': '$VERDICT',
    'exit_code': $FINAL_EXIT
}
print(json.dumps(result, ensure_ascii=False, indent=2))
")

# stdout에 JSON 출력
echo "$SUMMARY"

# $WORKSPACE/memory/logs/ci-latest.json 에 저장
mkdir -p "$(dirname "$CI_LOG_FILE")"
echo "$SUMMARY" > "$CI_LOG_FILE"
log "[CI] 결과 저장 완료: $CI_LOG_FILE"

exit $FINAL_EXIT
