#!/bin/sh
set -e

# Create necessary directories
mkdir -p /etc/rpi-sb-provisioner
mkdir -p /srv/rpi-sb-provisioner
mkdir -p /srv/rpi-sb-provisioner/tmp
mkdir -p /srv/rpi-sb-bootstrap
mkdir -p /var/log/rpi-sb-provisioner
[ -d /var/lock/rpi-sb-provisioner ] || mkdir -p /var/lock/rpi-sb-provisioner

# Default manufacturing DB path
MFG_DB_PATH="/srv/rpi-sb-provisioner/manufacturing.db"
STATE_DB_PATH="/srv/rpi-sb-provisioner/state.db"

# Source package defaults first
if [ -f "/usr/share/rpi-sb-provisioner/defaults/config" ]; then
    . /usr/share/rpi-sb-provisioner/defaults/config
fi

# Source user config overrides if present
if [ -f "/etc/rpi-sb-provisioner/config" ]; then
    . /etc/rpi-sb-provisioner/config
fi

# Invalidate every cached provisioning artefact in the configured workdir.
# rpi-sb-bootstrap.sh and the provisioner scripts treat $RPI_SB_WORKDIR as a
# persistent cache for signed fastboot gadget images (boot.img, boot.sig),
# signed bootcode (bootfiles.bin), signed EEPROM + config + bootcode
# (secure-bootloader/, non-secure-bootloader/), IDP boot artefacts
# (idp-signed-boot/), and staging .simg files. None of these are user data —
# they're all regenerable from /var/lib/rpi-sb-provisioner/ inputs and the
# firmware tree — but every one of them can silently mask a configuration
# change made via the UI/config until manually deleted.
#
# Wipe contents but keep the workdir itself, otherwise rpi-sb-bootstrap.sh's
# missing-dir check (`elif [ ! -d "${RPI_SB_WORKDIR}" ]`) falls back to a
# fresh temp dir and the user loses their configured path.
if [ -n "$RPI_SB_WORKDIR" ] && [ -d "$RPI_SB_WORKDIR" ]; then
    echo "Invalidating all cached provisioning artefacts in $RPI_SB_WORKDIR"
    find "$RPI_SB_WORKDIR" -mindepth 1 -maxdepth 1 -exec rm -rf -- {} +
fi

# Use the configured paths if set
if [ -n "$RPI_SB_PROVISIONER_MANUFACTURING_DB" ]; then
    MFG_DB_PATH="$RPI_SB_PROVISIONER_MANUFACTURING_DB"
fi

if [ -n "$RPI_SB_PROVISIONER_STATE_DB" ]; then
    STATE_DB_PATH="$RPI_SB_PROVISIONER_STATE_DB"
fi

# Create directory for state DB if needed
mkdir -p "$(dirname "$STATE_DB_PATH")"

# Initialize SQLite databases
if [ ! -f "$STATE_DB_PATH" ]; then
    touch "$STATE_DB_PATH"
    chmod 644 "$STATE_DB_PATH"
fi

# Define the expected schema for state.db devices table
STATE_DB_SCHEMA="id              integer primary key,
    serial          TEXT                not null,
    endpoint        TEXT                not null,
    state           TEXT                not null,
    image           TEXT                not null,
    ip_address      TEXT                not null,
    board_type      TEXT                not null default '',
    ts              timestamp           default current_timestamp"

# Ensure WAL journal mode
sqlite3 "$STATE_DB_PATH" "PRAGMA journal_mode=WAL;" > /dev/null 2>&1

# Check if the table exists in state.db
STATE_TABLE_EXISTS=$(sqlite3 "$STATE_DB_PATH" "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='devices';")

if [ "$STATE_TABLE_EXISTS" -eq 0 ]; then
    # Table doesn't exist, create it
    sqlite3 "$STATE_DB_PATH" "CREATE TABLE devices($STATE_DB_SCHEMA);" > /dev/null 2>&1
else
    # Table exists, check if migration is needed
    # Get current schema
    CURRENT_COLUMNS=$(sqlite3 "$STATE_DB_PATH" "PRAGMA table_info(devices);" | awk -F'|' '{print $2}' | tr '\n' ',')
    
    # Check if any expected columns are missing
    for COL in id serial endpoint state image ip_address board_type ts; do
        if ! echo "$CURRENT_COLUMNS" | grep -q "$COL"; then
            echo "Migration needed: column $COL is missing from state.db devices table"
            
            # Create a new table with correct schema
            sqlite3 "$STATE_DB_PATH" <<EOF
            CREATE TABLE devices_new($STATE_DB_SCHEMA);
            
            -- Copy data from old table to new table (handling all columns)
            INSERT INTO devices_new($(echo "$CURRENT_COLUMNS" | sed 's/,$//'))
            SELECT $(echo "$CURRENT_COLUMNS" | sed 's/,$//') 
            FROM devices;
            
            -- Drop old table
            DROP TABLE devices;
            
            -- Rename new table to original name
            ALTER TABLE devices_new RENAME TO devices;
EOF
            
            echo "Migration completed successfully for state.db"
            break
        fi
    done
fi

# Create directory for manufacturing DB if needed
mkdir -p "$(dirname "$MFG_DB_PATH")"

# Initialize manufacturing DB
if [ ! -f "$MFG_DB_PATH" ]; then
    touch "$MFG_DB_PATH"
    chmod 644 "$MFG_DB_PATH"
fi

# Define the expected schema for manufacturing.db devices table
# secure is set to 1 by default, as any prior release of rpi-sb-provisioner will have only offered secure provisioning
# Security tracking fields default to NULL to distinguish between not-applied vs unknown state
MFG_DB_SCHEMA="id              integer primary key,
    boardname       varchar(255)        not null,
    serial          char(8)             not null,
    eth_mac         char(17)            not null,
    wifi_mac        char(17)            not null,
    bt_mac          char(17)            not null,
    mmc_size        integer             not null,
    mmc_cid         char(32)            not null,
    rpi_duid        char(32)            not null,
    board_revision  varchar(255)        not null,
    processor       varchar(255)        not null,
    memory          varchar(255)        not null,
    manufacturer    varchar(255)        not null,
    secure          integer             not null DEFAULT 1,
    jtag_locked     integer             DEFAULT NULL,
    eeprom_write_protected integer      DEFAULT NULL,
    pubkey_programmed integer           DEFAULT NULL,
    devkey_revoked   integer            DEFAULT NULL,
    signed_boot_enabled integer         DEFAULT NULL,
    os_image_filename varchar(255)      DEFAULT NULL,
    os_image_sha256  char(64)           DEFAULT NULL,
    connect_registered integer          DEFAULT NULL,
    connect_device_id varchar(255)      DEFAULT NULL,
    eeprom_size     integer             DEFAULT NULL,
    eeprom_jedec    char(6)             DEFAULT NULL,
    eeprom_unique_id varchar(32)        DEFAULT NULL,
    bootloader_build_timestamp integer  DEFAULT NULL,
    provision_ts    timestamp           default current_timestamp"

# Ensure WAL journal mode
sqlite3 "$MFG_DB_PATH" "PRAGMA journal_mode=WAL;" > /dev/null 2>&1

# Check if the table exists in manufacturing.db
MFG_TABLE_EXISTS=$(sqlite3 "$MFG_DB_PATH" "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='devices';")

if [ "$MFG_TABLE_EXISTS" -eq 0 ]; then
    # Table doesn't exist, create it
    sqlite3 "$MFG_DB_PATH" "CREATE TABLE devices($MFG_DB_SCHEMA);" > /dev/null 2>&1
else
    # Table exists, check if migration is needed. The expected column set,
    # in schema order. Keep this in sync with MFG_DB_SCHEMA above.
    EXPECTED_COLS="id boardname serial eth_mac wifi_mac bt_mac mmc_size mmc_cid rpi_duid board_revision processor memory manufacturer secure jtag_locked eeprom_write_protected pubkey_programmed devkey_revoked signed_boot_enabled os_image_filename os_image_sha256 connect_registered connect_device_id eeprom_size eeprom_jedec eeprom_unique_id bootloader_build_timestamp provision_ts"

    # Current columns, one per line.
    CURRENT_COLUMNS=$(sqlite3 "$MFG_DB_PATH" "PRAGMA table_info(devices);" | awk -F'|' '{print $2}')

    # Migration is needed whenever the on-disk column set differs from the
    # expected set in either direction -- a missing column (added in this
    # release) or an extra column (dropped in this release).
    CURRENT_SORTED=$(printf '%s\n' $CURRENT_COLUMNS | sort)
    EXPECTED_SORTED=$(printf '%s\n' $EXPECTED_COLS | sort)

    if [ "$CURRENT_SORTED" != "$EXPECTED_SORTED" ]; then
        echo "Migration needed: manufacturing.db devices schema differs from expected"

        # Carry over only the columns present in BOTH the old and new schema.
        # Added columns are left at their DEFAULT; dropped columns (and their
        # data) are discarded.
        COMMON_COLS=""
        for COL in $EXPECTED_COLS; do
            if printf '%s\n' "$CURRENT_COLUMNS" | grep -qx "$COL"; then
                COMMON_COLS="${COMMON_COLS:+$COMMON_COLS,}$COL"
            fi
        done

        sqlite3 "$MFG_DB_PATH" <<EOF
        CREATE TABLE devices_new($MFG_DB_SCHEMA);

        -- Copy the intersection of old and new columns.
        INSERT INTO devices_new($COMMON_COLS)
        SELECT $COMMON_COLS
        FROM devices;

        -- Replace the old table with the migrated one.
        DROP TABLE devices;
        ALTER TABLE devices_new RENAME TO devices;
EOF

        echo "Migration completed successfully for manufacturing.db"
    fi
fi

#DEBHELPER#