#!/bin/bash
set -o pipefail

################################
# Configuration
################################
KERNEL_VERSION="$(uname -r | sed 's/\.x86_64$//')"
KERNEL_SRC="/root/rebootless/source"
PATCHES_DIR="/root/rebootless/${KERNEL_VERSION}_patches"
OUTPUT_DIR="/root/rebootless/kpatch_modules_${KERNEL_VERSION}"

################################
# Output files
################################
LOG_FILE="${OUTPUT_DIR}/build.log"
FAILED_LOG="${OUTPUT_DIR}/failed_patches.log"
SKIPPED_LOG="${OUTPUT_DIR}/skipped_patches.log"
SUCCESS_LOG="${OUTPUT_DIR}/success_patches.log"
REPORT_CSV="${OUTPUT_DIR}/kpatch_report.csv"
BASE_DIR="/root/rebootless"
DATA_DIR="$BASE_DIR/rebootlessdata"
#JSON_FILE="$DATA_DIR/${KERNEL_VERSION}_cve_index.json"

################################
# Colors
################################
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

################################
# Prepare output
################################
mkdir -p "${OUTPUT_DIR}"

: > "${SKIPPED_LOG}"
: > "${SUCCESS_LOG}"
[ ! -f "${FAILED_LOG}" ] && : > "${FAILED_LOG}"

echo "Kpatch build started at $(date)" >> "${LOG_FILE}"

# CSV header (create once)
if [ ! -f "${REPORT_CSV}" ]; then
    echo "CVE,PATCH_FILE,MODULE_BUILT,REASON" > "${REPORT_CSV}"
fi

################################
# Sanity checks
################################
command -v kpatch-build >/dev/null || { echo "ERROR: kpatch-build not found"; exit 1; }
[ ! -f "${KERNEL_SRC}/vmlinux" ] && { echo "ERROR: vmlinux missing"; exit 1; }

################################
# Clean stale kpatch workspace
################################
rm -rf ~/.kpatch/tmp/* 2>/dev/null

################################
# Main loop
################################

while read -r PATCH_PATH; do
    PATCH_PATH=$(readlink -f "${PATCH_PATH}")
    [ ! -f "${PATCH_PATH}" ] && continue

    PATCH_FILE=$(basename "${PATCH_PATH}")
    BASENAME="${PATCH_FILE%.patch}"
    CVE=$(echo "${BASENAME}" | grep -oE 'CVE-[0-9]{4}-[0-9]+' || echo "UNKNOWN")

    MODULE_NAME="${BASENAME}"
    OUTPUT_MODULE="${OUTPUT_DIR}/${MODULE_NAME}.ko"

    ################################
    # Skip: previous failure
    ################################
    if grep -q "Patch  : ${PATCH_FILE}" "${FAILED_LOG}"; then
        echo -e "${YELLOW}↷ Skipping ${PATCH_FILE} (previous failure)${NC}"
        echo "${CVE},${PATCH_FILE},NO,previous failure" >> "${REPORT_CSV}"
        continue
    fi

    ################################
    # Skip: already built (FULL HASH MODE)
    ################################
    if [ -f "${OUTPUT_MODULE}" ]; then
        echo -e "${GREEN}↷ Skipping ${PATCH_FILE} (already built)${NC}"
        echo "${CVE},${PATCH_FILE},YES," >> "${REPORT_CSV}"
        continue
    fi

    ################################
    # Log header
    ################################
    {
        echo ""
        echo "=================================================="
        echo "PATCH : ${PATCH_FILE}"
        echo "CVE   : ${CVE}"
        echo "TIME  : $(date)"
        echo "=================================================="
    } >> "${LOG_FILE}"

    echo -e "${GREEN}Building ${PATCH_FILE}${NC}"

    ################################
    # Cleanup stale livepatch outputs
    ################################
    rm -f "${OUTPUT_DIR}/livepatch-"*.ko 2>/dev/null

    ################################
    # Build
    ################################
    if (
        cd "${OUTPUT_DIR}" || exit 1
        kpatch-build \
            --skip-compiler-check \
            --non-replace \
            --sourcedir "${KERNEL_SRC}" \
            --vmlinux "${KERNEL_SRC}/vmlinux" \
            "${PATCH_PATH}"
    ) >> "${LOG_FILE}" 2>&1; then

        GENERATED_KO=$(ls -t "${OUTPUT_DIR}/livepatch-"*.ko 2>/dev/null | head -1)

        if [ -z "${GENERATED_KO}" ]; then
            echo "${CVE},${PATCH_FILE},NO,no module produced" >> "${REPORT_CSV}"
            continue
        fi

        mv "${GENERATED_KO}" "${OUTPUT_MODULE}"

        echo -e "${GREEN}✓ Success: ${MODULE_NAME}.ko${NC}"
        echo "$(date) SUCCESS ${PATCH_FILE}" >> "${SUCCESS_LOG}"
        echo "${CVE},${PATCH_FILE},YES," >> "${REPORT_CSV}"

        # update json

        # jq --arg cve "$CVE" \
        # --arg fname "$PATCH_FILE" \
        # '
        # .[$cve].selected_patch |=
        #     if .filename == $fname
        #     then . + { livepatch_compatible: true }
        #     else .
        #     end
        # ' "$JSON_FILE" > "${JSON_FILE}.tmp" && mv "${JSON_FILE}.tmp" "$JSON_FILE"


    else
        REASON=$(grep -iE \
            'no changed objects found|Jump labels|failed to apply|unsupported|ERROR:' \
            "${LOG_FILE}" | tail -1)

        REASON=${REASON:-"kpatch build failure"}

        {
            echo "--------------------------------------------------"
            echo "[FAIL] ${CVE}"
            echo "Patch  : ${PATCH_FILE}"
            echo "Reason : ${REASON}"
            echo "Time   : $(date)"
        } >> "${FAILED_LOG}"

        echo -e "${RED}✗ Failed: ${PATCH_FILE}${NC}"
        echo "${CVE},${PATCH_FILE},NO,${REASON//,/;}" >> "${REPORT_CSV}"
    fi

done < <(find "${PATCHES_DIR}" -type f -name "*.patch" | sort)

echo ""
echo "=========================================="
echo "Build complete"
echo "CSV report:"
echo "  ${REPORT_CSV}"
echo "=========================================="
