#!/bin/bash
# Check if we are running as root
if [ "$EUID" -ne 0 ]; then
    echo "Error: This script must be run as root"
    exit 1
fi

# Check if the correct number of arguments is provided
if [ "$#" -ne 2 ]; then
    echo "Usage: $0 <OS_VERSION> <RAW_DEVICE>"
    echo "Example: $0 24.1 /dev/mmcblk0"
    exit 1
fi

OS_VERSION=$1
RAW_DEVICE=$2

# Check for required tools
for tool in virt-install wget bunzip2 genisoimage virsh; do
    if ! command -v $tool &> /dev/null; then
        echo "Error: $tool is not installed"
        exit 1
    fi
done

if [ ! -f /tmp/opnsense-install.img.bz2 ]; then
    # Download the OPNsense serial USB image
    echo "Downloading OPNsense USB serial image for version $OS_VERSION"
    wget -O /tmp/opnsense-install.img.bz2 \
    https://mirror.ams1.nl.leaseweb.net/opnsense/releases/${OS_VERSION}/OPNsense-${OS_VERSION}-serial-amd64.img.bz2

    if [ $? -ne 0 ]; then
        echo "Error: Failed to download image"
        exit 1
    fi
fi

if [ ! -f /tmp/opnsense-install.img ]; then
    # Unpack the image
    echo "Unpacking OPNsense image..."
    bunzip2 -c /tmp/opnsense-install.img.bz2 > /tmp/opnsense-install.img
fi

# Generate config.xml on the fly
echo "Generating config.xml..."
TMPDIR=$(mktemp -d)
mkdir -p "$TMPDIR/config"

# Use env var or fallback password
DEFAULT_PASSWORD="opnsense"
ADMIN_PASSWORD="${OPNSENSE_ADMIN_PASSWORD:-$DEFAULT_PASSWORD}"
HASHED_PASS=$(openssl passwd -1 "$ADMIN_PASSWORD")

cat > "$TMPDIR/config/config.xml" <<EOF
<?xml version="1.0"?>
<opnsense>
  <version>${OS_VERSION}</version>
  <system>
    <hostname>opnsense</hostname>
    <domain>local</domain>
    <timezone>UTC</timezone>
    <username>root</username>
    <password>${HASHED_PASS}</password>
    <webgui>
      <protocol>https</protocol>
      <port>443</port>
    </webgui>
    <ssh>
      <enable>1</enable>
      <port>22</port>
      <passwordauth>1</passwordauth>
    </ssh>
  </system>
  <interfaces>
    <lan>
      <if>em1</if>
      <ipaddr>10.19.4.254</ipaddr>
      <subnet>24</subnet>
      <descr>LAN</descr>
    </lan>
    <wan>
      <if>em0</if>
      <ipaddr>dhcp</ipaddr>
      <descr>WAN</descr>
    </wan>
  </interfaces>
  <gateways>
    <defaultgw4>
      <interface>wan</interface>
    </defaultgw4>
  </gateways>
  <dhcpd>
    <lan>
      <enable>1</enable>
      <range>
        <from>10.19.4.100</from>
        <to>10.19.4.199</to>
      </range>
    </lan>
  </dhcpd>
  <unbound>
    <enable>1</enable>
    <dnssec>1</dnssec>
    <active_interface>lan</active_interface>
    <outgoing_interface>wan</outgoing_interface>
  </unbound>
</opnsense>
EOF

# Verify config.xml was created
if [ ! -f "$TMPDIR/config/config.xml" ]; then
    echo "Error: config.xml was not created properly."
    exit 1
fi

# Create config ISO
echo "Creating config ISO..."
genisoimage -o /tmp/config.iso -V config -r "$TMPDIR"

# Run the VM
echo "Launching VM to install OPNsense on ${RAW_DEVICE}"
virt-install \
  --name opnsense-vm \
  --ram 2048 \
  --vcpus 2 \
  --os-variant freebsd13.1 \
  --import \
  --disk path=/tmp/opnsense-install.img,format=raw,readonly=on \
  --disk path=${RAW_DEVICE},format=raw \
  --disk path=/tmp/config.iso,device=cdrom,readonly=on \
  --network network=default,model=virtio \
  --network network=default,model=virtio \
  --network network=default,model=virtio \
  --graphics none \
  --console pty,target_type=serial \
  --boot hd \
  --noautoconsole

# Attach to the VM console
virsh console opnsense-vm

if [ $? -ne 0 ]; then
    echo "Failed to start VM or connect to console"
    exit 1
fi

echo "OPNsense installation complete. You may now shut down the VM and transfer the SD card to your APU1D."

# Clean up temporary files
echo "Cleaning up..."
rm -f /tmp/opnsense-install.img /tmp/opnsense-install.img.bz2 /tmp/config.iso
rm -rf /tmp/opnsense-config

echo "Done."
