#!/bin/sh
# Clawdie Shell — Package Configuration Module
# Purpose: Configure package repositories and seed offline cache
# POSIX-compliant (no bash-isms)

set -eu

# Configuration (can be overridden for testing)
PKG_CONF_DIR="${PKG_CONF_DIR:-/etc/pkg/repos}"
FREEBSD_REPO_CONF="${FREEBSD_REPO_CONF:-$PKG_CONF_DIR/FreeBSD.conf}"
CLAWDIE_USB_REPO_CONF="${CLAWDIE_USB_REPO_CONF:-$PKG_CONF_DIR/Clawdie-USB.conf}"
USB_MOUNT_POINT="${USB_MOUNT_POINT:-/mnt/media}"
USB_PKG_PATH="${USB_PKG_PATH:-$USB_MOUNT_POINT/packages}"
BASTILLE_PKG_CACHE="${BASTILLE_PKG_CACHE:-/var/cache/pkg/bastille}"
LOG_FILE="${LOG_FILE:-/var/log/clawdie-firstboot.log}"
PROGRESS_FILE="${PROGRESS_FILE:-/var/log/clawdie-firstboot.progress}"

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

clawdie_shell_pkg_setup() {
  # Main orchestrator: configure repos and seed package cache

  log_msg "[pkg] Starting package configuration"

  # Step 1: Detect system ABI
  local abi
  abi=$(clawdie_shell_pkg_detect_abi) || {
    log_msg "[pkg] ERROR: Could not detect ABI"
    return 1
  }
  log_msg "[pkg] System ABI: $abi"

  # Step 2: Write FreeBSD repo config (latest or quarterly per build.cfg)
  clawdie_shell_pkg_write_freebsd_conf "$abi" || {
    log_msg "[pkg] ERROR: Failed to write FreeBSD repo config"
    return 1
  }
  log_msg "[pkg] Configured FreeBSD repository"

  # Step 3: Write Clawdie USB repo config (offline)
  clawdie_shell_pkg_write_clawdie_conf || {
    log_msg "[pkg] ERROR: Failed to write Clawdie repo config"
    return 1
  }
  log_msg "[pkg] Configured Clawdie USB repository"

  # Step 4: Seed Bastille package cache from USB
  clawdie_shell_pkg_seed_cache || {
    log_msg "[pkg] WARNING: Failed to seed package cache"
  }
  log_msg "[pkg] Package cache seeded"

  echo "[PKG] SUCCESS" >> "$PROGRESS_FILE"
  log_msg "[pkg] Package configuration complete"
}

# ============================================================================
# ABI DETECTION
# ============================================================================

clawdie_shell_pkg_detect_abi() {
  # Detect FreeBSD system ABI
  # Returns: ABI string (e.g., "FreeBSD:15:amd64")

  local abi

  abi=$(pkg config abi 2>/dev/null || true)

  if [ -z "$abi" ]; then
    # Fallback: construct from uname
    local os_name os_release arch
    os_name=$(uname -s)
    os_release=$(uname -r | cut -d. -f1)
    arch=$(uname -m)
    abi="$os_name:$os_release:$arch"
  fi

  echo "$abi"
}

# ============================================================================
# REPOSITORY CONFIGURATION
# ============================================================================

clawdie_shell_pkg_write_freebsd_conf() {
  # Write FreeBSD repository configuration
  # Input: ABI string
  # Reads DEFAULT_PKG_BRANCH from build.cfg (latest or quarterly)

  local abi="$1"
  local branch="${DEFAULT_PKG_BRANCH:-latest}"

  if [ ! -d "$PKG_CONF_DIR" ]; then
    mkdir -p "$PKG_CONF_DIR"
  fi

  # Remove existing FreeBSD.conf if present
  rm -f "$FREEBSD_REPO_CONF" 2>/dev/null || true

  # Write new config
  cat > "$FREEBSD_REPO_CONF" <<EOF
FreeBSD: {
  url: "pkg+https://pkg.FreeBSD.org/\${ABI}/$branch",
  mirror_type: "srv",
  enabled: yes
}
EOF

  log_msg "[pkg] Wrote $FREEBSD_REPO_CONF with branch=$branch"
}

clawdie_shell_pkg_write_clawdie_conf() {
  # Write Clawdie USB repository configuration (offline)
  # Points to bundled packages on USB

  if [ ! -d "$PKG_CONF_DIR" ]; then
    mkdir -p "$PKG_CONF_DIR"
  fi

  # Remove existing Clawdie-USB.conf if present
  rm -f "$CLAWDIE_USB_REPO_CONF" 2>/dev/null || true

  # Write new config
  cat > "$CLAWDIE_USB_REPO_CONF" <<EOF
Clawdie-USB: {
  url: "file://$USB_PKG_PATH",
  mirror_type: "none",
  enabled: yes,
  priority: 100
}
EOF

  log_msg "[pkg] Wrote $CLAWDIE_USB_REPO_CONF pointing to $USB_PKG_PATH"
}

# ============================================================================
# PACKAGE CACHE SEEDING
# ============================================================================

clawdie_shell_pkg_seed_cache() {
  # Copy USB packages to Bastille cache directory
  # This allows jails to use cached packages even if offline

  if [ ! -d "$USB_PKG_PATH" ]; then
    log_msg "[pkg] USB packages not available: $USB_PKG_PATH"
    return 0  # Not an error, just skip
  fi

  if [ ! -d "$BASTILLE_PKG_CACHE" ]; then
    mkdir -p "$BASTILLE_PKG_CACHE"
    log_msg "[pkg] Created cache directory: $BASTILLE_PKG_CACHE"
  fi

  # Copy .pkg files to cache
  if find "$USB_PKG_PATH" -name "*.pkg" -type f 2>/dev/null | head -1 >/dev/null; then
    cp "$USB_PKG_PATH"/*.pkg "$BASTILLE_PKG_CACHE" 2>/dev/null || true
    log_msg "[pkg] Seeded Bastille cache from USB packages"
  else
    log_msg "[pkg] WARNING: No .pkg files found in $USB_PKG_PATH"
  fi

  return 0
}

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

clawdie_shell_pkg_validate() {
  # Verify package configuration

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

  if ! grep -q "FreeBSD:" "$FREEBSD_REPO_CONF" 2>/dev/null; then
    log_msg "[pkg] ERROR: Invalid FreeBSD.conf format"
    return 1
  fi

  log_msg "[pkg] Package configuration validation passed"
  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_PKG_TEST:-0}" -eq 0 ]; then
  clawdie_shell_pkg_setup
fi
