#!/usr/bin/env bash
# build-linux-rpi.sh - build/install a newer linux-rpi from rpi-6.18.y
set -euo pipefail

if [[ ${EUID:-0} -ne 0 ]]; then
  echo "run as root (sudo) to install build deps and kernel packages" >&2
  exit 1
fi

BUILD_USER=${LESAVKA_KERNEL_BUILD_USER:-${SUDO_USER:-$(id -un)}}
if [[ -z $BUILD_USER || $BUILD_USER == root ]]; then
  echo "missing non-root build user; set LESAVKA_KERNEL_BUILD_USER" >&2
  exit 1
fi

KERNEL_REPO=${LESAVKA_KERNEL_REPO:-https://github.com/raspberrypi/linux.git}
KERNEL_BRANCH=${LESAVKA_KERNEL_BRANCH:-rpi-6.18.y}
KERNEL_COMMIT=${LESAVKA_KERNEL_COMMIT:-}
PKGBUILD_REPO=${LESAVKA_KERNEL_PKG_REPO:-https://github.com/archlinuxarm/PKGBUILDs.git}
BUILD_ROOT=${LESAVKA_KERNEL_BUILD_ROOT:-/var/tmp/lesavka-linux-rpi}
PKGREL=${LESAVKA_KERNEL_PKGREL:-2}
JOBS=${LESAVKA_KERNEL_JOBS:-2}
SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
PATCH_DIR=${LESAVKA_KERNEL_PATCH_DIR:-$SCRIPT_DIR}
PATCH_DWC2_FIFO=${LESAVKA_KERNEL_PATCH_DWC2_FIFO:-}
PATCH_UVC_BULK=${LESAVKA_KERNEL_PATCH_UVC_BULK:-}
PATCH_UVC_DEBUG=${LESAVKA_KERNEL_PATCH_UVC_DEBUG:-}
SKIP_CPUINFO_PATCH=${LESAVKA_KERNEL_SKIP_CPUINFO_PATCH:-}

if [[ -z $KERNEL_COMMIT ]]; then
  KERNEL_COMMIT=$(git ls-remote "$KERNEL_REPO" "refs/heads/$KERNEL_BRANCH" | awk '{print $1}')
fi
if [[ -z $KERNEL_COMMIT ]]; then
  echo "failed to resolve kernel commit for $KERNEL_BRANCH" >&2
  exit 1
fi

KERNEL_VERSION=$(
  curl -fsSL "https://raw.githubusercontent.com/raspberrypi/linux/$KERNEL_COMMIT/Makefile" |
    awk -F' = ' '
      /^VERSION =/ {v=$2}
      /^PATCHLEVEL =/ {p=$2}
      /^SUBLEVEL =/ {s=$2}
      END { if (v && p && s) print v "." p "." s }'
)
if [[ -z $KERNEL_VERSION ]]; then
  echo "failed to determine kernel version from $KERNEL_COMMIT" >&2
  exit 1
fi

TARGET_VERSION="${KERNEL_VERSION}-${PKGREL}"
INSTALLED_VERSION=$(pacman -Qi linux-rpi 2>/dev/null | awk -F': ' '/Version/{print $2}')
if [[ -n $INSTALLED_VERSION && $INSTALLED_VERSION == "$TARGET_VERSION"* ]]; then
  echo "linux-rpi already at $TARGET_VERSION"
  exit 0
fi

echo "==> Building linux-rpi $KERNEL_VERSION ($KERNEL_COMMIT) pkgrel=$PKGREL"

pacman -Sy --needed --noconfirm git bc kmod inetutils base-devel

rm -rf "$BUILD_ROOT"
mkdir -p "$BUILD_ROOT"
chown "$BUILD_USER":"$BUILD_USER" "$BUILD_ROOT"

sudo -u "$BUILD_USER" git clone --depth 1 "$PKGBUILD_REPO" "$BUILD_ROOT/PKGBUILDs"
cp -a "$BUILD_ROOT/PKGBUILDs/core/linux-rpi" "$BUILD_ROOT/linux-rpi"
chown -R "$BUILD_USER":"$BUILD_USER" "$BUILD_ROOT/linux-rpi"

if [[ -n $SKIP_CPUINFO_PATCH ]]; then
  BUILD_ROOT="$BUILD_ROOT" python - <<'PY'
from pathlib import Path
import os

pkgbuild = Path(os.environ["BUILD_ROOT"]) / "linux-rpi" / "PKGBUILD"
text = pkgbuild.read_text()
needle = "  patch -p1 -i ../0001-Make-proc-cpuinfo-consistent-on-arm64-and-arm.patch\n"
if needle in text:
    text = text.replace(
        needle,
        "  echo \"Skipping proc-cpuinfo compatibility patch\"\n",
        1,
    )
pkgbuild.write_text(text)
PY
fi

sudo -u "$BUILD_USER" bash -c "
  set -euo pipefail
  cd '$BUILD_ROOT/linux-rpi'
  sed -i 's/^pkgver=.*/pkgver=$KERNEL_VERSION/' PKGBUILD
  sed -i 's/^pkgrel=.*/pkgrel=$PKGREL/' PKGBUILD
  sed -i 's/^_commit=.*/_commit=$KERNEL_COMMIT/' PKGBUILD
  makepkg -g > /tmp/lesavka-kernel.sums
"

sudo -u "$BUILD_USER" BUILD_ROOT="$BUILD_ROOT" python - <<'PY'
import re
from pathlib import Path
import os

root = Path(os.environ["BUILD_ROOT"])
pkgbuild = root / "linux-rpi" / "PKGBUILD"
sums = Path("/tmp/lesavka-kernel.sums").read_text().splitlines()
text = pkgbuild.read_text()
for line in sums:
    if not line.startswith("sha256sums"):
        continue
    key = line.split("=", 1)[0]
    text = re.sub(rf"^{re.escape(key)}=.*$", line, text, flags=re.M)
pkgbuild.write_text(text)
PY

MAKEPKG_EXTRA=""
KERNEL_SRC="$BUILD_ROOT/linux-rpi/src/linux-$KERNEL_COMMIT"
PATCHES=()
if [[ -n $PATCH_DWC2_FIFO ]]; then
  PATCHES+=("dwc2-fifo.patch")
fi
if [[ -n $PATCH_UVC_BULK ]]; then
  PATCHES+=("uvc-bulk.patch")
fi
if [[ -n $PATCH_UVC_DEBUG ]]; then
  PATCHES+=("uvc-debug.patch")
fi
if [[ ${#PATCHES[@]} -gt 0 ]]; then
  sudo -u "$BUILD_USER" bash -c "
    set -euo pipefail
    cd '$BUILD_ROOT/linux-rpi'
    MAKEFLAGS='-j$JOBS' makepkg -o --noconfirm
  "
  sudo -u "$BUILD_USER" bash -c "
    set -euo pipefail
    src='$KERNEL_SRC'
    if [[ ! -d \$src ]]; then
      echo \"missing kernel source \$src\" >&2
      exit 1
    fi
    cd \"\$src\"
    for patch in ${PATCHES[*]}; do
      patch_file='$PATCH_DIR/'\"\$patch\"
      if [[ ! -f \$patch_file ]]; then
        echo \"missing patch \$patch_file\" >&2
        exit 1
      fi
      case \"\$patch\" in
        dwc2-fifo.patch)
          if grep -q 'dwc2_check_param_fifo_total' \"drivers/usb/dwc2/params.c\"; then
            echo \"dwc2-fifo patch already applied\"
            continue
          fi
          ;;
        uvc-bulk.patch)
          if grep -q 'streaming_bulk' \"drivers/usb/gadget/function/uvc_configfs.c\"; then
            echo \"uvc-bulk patch already applied\"
            continue
          fi
          ;;
        uvc-debug.patch)
          if grep -q 'uvcg_video_enable: missing uvc/func/config' \
            \"drivers/usb/gadget/function/uvc_video.c\"; then
            echo \"uvc-debug patch already applied\"
            continue
          fi
          ;;
      esac
      patch -p1 < \"\$patch_file\"
    done
  "
  MAKEPKG_EXTRA="-e"
fi

sudo -u "$BUILD_USER" bash -c "
  set -euo pipefail
  cd '$BUILD_ROOT/linux-rpi'
  MAKEFLAGS='-j$JOBS' makepkg -s --noconfirm $MAKEPKG_EXTRA
"

mapfile -t PKGS < <(ls "$BUILD_ROOT/linux-rpi"/*.pkg.tar.* 2>/dev/null)
if [[ ${#PKGS[@]} -eq 0 ]]; then
  echo "no kernel packages built" >&2
  exit 1
fi

pacman -U --noconfirm "${PKGS[@]}"
echo "✅ linux-rpi upgraded to $TARGET_VERSION (reboot required)"
