#!/bin/sh
# Clawdie Shell — GPU Detection Module
# Purpose: Detect GPU and configure appropriate kernel modules
# POSIX-compliant (no bash-isms)

set -eu

# Configuration (can be overridden for testing)
RC_CONF="${RC_CONF:-/etc/rc.conf}"
LOG_FILE="${LOG_FILE:-/var/log/clawdie-firstboot.log}"
PROGRESS_FILE="${PROGRESS_FILE:-/var/log/clawdie-firstboot.progress}"

# ============================================================================
# MAIN ENTRY POINT
# ============================================================================

clawdie_shell_gpu_detect() {
  # Main orchestrator: detect GPU and write rc.conf
  # Sets DETECTED_GPU for use by other modules

  log_msg "[gpu] Starting GPU detection"

  # Query pciconf for GPU vendor
  gpu_vendor=$(clawdie_shell_gpu_detect_pci)

  if [ -z "$gpu_vendor" ]; then
    log_msg "[gpu] No GPU detected — using VESA fallback"
    DETECTED_GPU="vesa"
    echo "[GPU] VESA" >> "$PROGRESS_FILE"
    return 0
  fi

  log_msg "[gpu] Detected GPU vendor: $gpu_vendor"

  # Convert vendor to driver module list
  kld_list=$(clawdie_shell_gpu_match_driver "$gpu_vendor")
  DETECTED_GPU="$gpu_vendor"

  if [ -z "$kld_list" ]; then
    log_msg "[gpu] Vendor '$gpu_vendor' has no driver — using VESA fallback"
    DETECTED_GPU="vesa"
    echo "[GPU] VESA (unknown vendor)" >> "$PROGRESS_FILE"
    return 0
  fi

  log_msg "[gpu] Matched driver: $kld_list"

  # Write to rc.conf
  clawdie_shell_gpu_write_rcconf "$kld_list"
  log_msg "[gpu] Updated rc.conf with kld_list"

  echo "[GPU] $DETECTED_GPU ($kld_list)" >> "$PROGRESS_FILE"
  log_msg "[gpu] GPU detection complete"
}

# ============================================================================
# GPU DETECTION VIA PCICONF
# ============================================================================

clawdie_shell_gpu_detect_pci() {
  # Query pciconf for GPU vendor
  # Returns: intel, amd, nvidia, vmware, or empty string

  local pciconf_out

  # Get pciconf output (filter to VGA device)
  pciconf_out=$(pciconf -lv 2>/dev/null | grep -i "class=0x030000" | head -1 || true)

  if [ -z "$pciconf_out" ]; then
    return
  fi

  # Extract vendor string
  if echo "$pciconf_out" | grep -iq "Intel"; then
    echo "intel"
  elif echo "$pciconf_out" | grep -iq "AMD\|ATI"; then
    echo "amd"
  elif echo "$pciconf_out" | grep -iq "NVIDIA"; then
    echo "nvidia"
  elif echo "$pciconf_out" | grep -iq "VMware"; then
    echo "vmware"
  fi
}

# ============================================================================
# DRIVER LOOKUP TABLE
# ============================================================================

clawdie_shell_gpu_match_driver() {
  # Convert vendor to kernel module list
  # Input: intel, amd, nvidia, vmware, or vendor string
  # Output: space-separated kld module names (e.g., "i915kms" or "nvidia-modeset nvidia")

  local vendor="$1"

  case "$vendor" in
    intel)
      echo "i915kms"
      ;;
    amd)
      echo "amdgpu"
      ;;
    nvidia)
      # NVIDIA driver is set separately by clawdie_shell_nvidia_detect()
      # This module just returns the base driver name
      echo "nvidia-modeset nvidia"
      ;;
    vmware)
      echo "vmwgfx"
      ;;
    *)
      # Unknown vendor — no driver
      return
      ;;
  esac
}

# ============================================================================
# RC.CONF WRITING
# ============================================================================

clawdie_shell_gpu_write_rcconf() {
  # Write kld_list to rc.conf
  # Input: space-separated module list (e.g., "i915kms" or "nvidia-modeset nvidia")

  local kld_list="$1"

  if [ ! -f "$RC_CONF" ]; then
    log_msg "[gpu] Creating $RC_CONF"
    touch "$RC_CONF"
  fi

  # If kld_list is empty (VESA), skip writing anything
  if [ -z "$kld_list" ]; then
    log_msg "[gpu] No driver — skipping kld_list (VESA fallback)"
    return 0
  fi

  # Remove existing kld_list if present
  if grep -q "^kld_list=" "$RC_CONF" 2>/dev/null; then
    sed -i.bak '/^kld_list=/d' "$RC_CONF"
    rm -f "$RC_CONF.bak"
  fi

  # Append new kld_list
  echo "kld_list=\"$kld_list\"" >> "$RC_CONF"
  log_msg "[gpu] Wrote kld_list=$kld_list to $RC_CONF"
}

# ============================================================================
# VALIDATION
# ============================================================================

clawdie_shell_gpu_validate() {
  # Verify rc.conf has valid kld_list (if GPU detected)

  if [ ! -f "$RC_CONF" ]; then
    log_msg "[gpu] ERROR: $RC_CONF not found"
    return 1
  fi

  if grep -q "^kld_list=" "$RC_CONF" 2>/dev/null; then
    local kld=$(grep "^kld_list=" "$RC_CONF" | cut -d= -f2 | tr -d '"' | head -1)
    if [ -z "$kld" ]; then
      log_msg "[gpu] ERROR: kld_list is empty"
      return 1
    fi
  fi

  return 0
}

# ============================================================================
# LOGGING HELPER
# ============================================================================

log_msg() {
  echo "$(date '+%H:%M:%S') $1" | tee -a "$LOG_FILE" 2>/dev/null || true
}

# Only run if sourced directly (not during test)
if [ "${SHELL_GPU_TEST:-0}" -eq 0 ]; then
  clawdie_shell_gpu_detect
fi
