#!/bin/bash

if [[ "$PATH" != *"$SNAP_INSTANCE_NAME"* ]]; then
  export PATH="${PATH/\/snap\/wekan\//\/snap\/$SNAP_INSTANCE_NAME\/}"
fi

# MongoDB Control Script
# Starts MongoDB 7.x server only

# get wekan/mongo settings
echo "Reading snap settings..."
source $SNAP/bin/wekan-read-settings

# Debug: Show what we got from snap settings
echo "Snap settings loaded:"
echo "  MONGODB_BIND_IP: '${MONGODB_BIND_IP}'"
echo "  MONGODB_PORT: '${MONGODB_PORT}'"
echo "  MONGODB_BIND_UNIX_SOCKET: '${MONGODB_BIND_UNIX_SOCKET}'"

# Debug: Check snap settings directly
echo "Direct snap settings check:"
echo "  mongodb-port: $(snapctl get mongodb-port 2>/dev/null || echo 'not set')"
echo "  mongodb-bind-ip: $(snapctl get mongodb-bind-ip 2>/dev/null || echo 'not set')"
echo "  mongodb-bind-unix-socket: $(snapctl get mongodb-bind-unix-socket 2>/dev/null || echo 'not set')"

if [ "true" == "${DISABLE_MONGODB}" ]; then
    echo "mongodb is disabled. Stop service"
    snapctl stop --disable ${SNAP_NAME}.mongodb
    exit 0
fi

# make sure we have set minimum env variables for locale
if [ -z "${LANG}" ]; then
    export LANG=en_US.UTF-8
fi

export LC_ALL=C
# If CPU does not support required instructions (AVX for x86_64, ARMv8.2-A for arm64),
# migratemongo/avx wrapper scripts transparently re-run MongoDB commands via QEMU.
# See https://github.com/wekan/migratemongo
export PATH=$SNAP/migratemongo/avx:$SNAP/usr/bin:$SNAP/bin:${PATH}
export LD_LIBRARY_PATH=$SNAP/lib:$SNAP/lib/x86_64-linux-gnu:$SNAP/lib/aarch64-linux-gnu:${LD_LIBRARY_PATH}

# If temporary settings log exists, delete it
if [ -f ${SNAP_COMMON}/settings.log ]; then
    rm ${SNAP_COMMON}/settings.log
fi

# Set MongoDB log destination to snapcommon for log file detection
export MONGO_LOG_DESTINATION="snapcommon"

# Set MongoDB data directory
export MONGO_DATA_DIR="${SNAP_COMMON}"

# Create MongoDB data directory if it doesn't exist
if [ ! -d "$MONGO_DATA_DIR" ]; then
    mkdir -p "$MONGO_DATA_DIR"
    chmod 755 "$MONGO_DATA_DIR"
fi

# Set MongoDB log file path
export MONGO_LOG_FILE="${SNAP_COMMON}/mongodb.log"

# Build bind options from snap settings
BIND_OPTIONS=""
if [ "nill" != "${MONGODB_BIND_UNIX_SOCKET}" ] && [ -n "${MONGODB_BIND_UNIX_SOCKET}" ]; then
    BIND_OPTIONS+=" --unixSocketPrefix ${MONGODB_BIND_UNIX_SOCKET}"
fi
if [ -n "${MONGODB_BIND_IP}" ]; then
    BIND_OPTIONS+=" --bind_ip ${MONGODB_BIND_IP}"
else
    BIND_OPTIONS+=" --bind_ip 127.0.0.1"
fi
if [ -n "${MONGODB_PORT}" ]; then
    BIND_OPTIONS+=" --port ${MONGODB_PORT}"
fi

# Debug: Show what settings we're using
echo "MongoDB settings:"
echo "  MONGODB_BIND_IP: ${MONGODB_BIND_IP:-127.0.0.1}"
echo "  MONGODB_PORT: ${MONGODB_PORT}"
echo "  MONGODB_BIND_UNIX_SOCKET: ${MONGODB_BIND_UNIX_SOCKET:-not set}"
echo "  BIND_OPTIONS: ${BIND_OPTIONS}"

# Check if MongoDB is already running
check_mongodb_running() {
    local port="${MONGODB_PORT}"

    # Check if MongoDB is already running on the configured port
    if netstat -tuln 2>/dev/null | grep -q ":${port} "; then
        echo "MongoDB is already running on port ${port}"
        return 0
    fi

    # Alternative check using lsof if netstat is not available
    if command -v lsof >/dev/null 2>&1; then
        if lsof -i ":${port}" >/dev/null 2>&1; then
            echo "MongoDB is already running on port ${port} (detected via lsof)"
            return 0
        fi
    fi

    # Check if there's a PID file and the process is still running
    if [ -f "${SNAP_COMMON}/mongodb.pid" ]; then
        local pid=$(cat "${SNAP_COMMON}/mongodb.pid" 2>/dev/null)
        if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
            echo "MongoDB is already running (PID: $pid)"
            return 0
        else
            # Remove stale PID file
            rm -f "${SNAP_COMMON}/mongodb.pid"
        fi
    fi

    return 1
}

# Cleanup function to remove PID file on exit
cleanup() {
    rm -f "${SNAP_COMMON}/mongodb.pid"
}
trap cleanup EXIT

# Check if MongoDB is already running
if check_mongodb_running; then
    echo "MongoDB is already running. Exiting to prevent multiple instances."
    exit 0
fi

# Start MongoDB 7.x server
echo "Starting MongoDB 7.x server..."
# Create PID file
echo $$ > "${SNAP_COMMON}/mongodb.pid"

# Determine the expected replica set member host:port.
# Priority: port extracted from MONGO_URL if it points to localhost,
# otherwise the mongodb-port snap config (MONGODB_PORT).
INIT_MARKER="${SNAP_COMMON}/.replica_set_initialized"
_RS_PORT="${MONGODB_PORT:-27019}"
if [ -n "$MONGO_URL" ]; then
    _url_port=$(echo "$MONGO_URL" | sed -nE 's#mongodb://([^@]+@)?(127\.0\.0\.1|localhost):([0-9]+)/.*#\3#p')
    [ -n "$_url_port" ] && _RS_PORT="$_url_port"
fi
RS_MEMBER_HOST="127.0.0.1:${_RS_PORT}"
echo "Replica set member host: ${RS_MEMBER_HOST}"

# Always start MongoDB temporarily in background to verify/fix replica set
# config before the final foreground start.  This catches first-run,
# port changes, and corrupt/missing replica set state.
# Use --pidfilepath so we can kill exactly this process without touching
# MongoDB instances from other parallel snap installs.
TEMP_PID_FILE="${SNAP_COMMON}/mongod-temp.pid"
echo "Starting MongoDB temporarily to check replica set configuration..."
$SNAP/bin/mongod \
    --dbpath="$MONGO_DATA_DIR" \
    --logpath="$MONGO_LOG_FILE" \
    --logappend $BIND_OPTIONS \
    --storageEngine wiredTiger --wiredTigerCacheSizeGB 32 \
    --timeZoneInfo /usr/share/zoneinfo \
    --setParameter logicalSessionRefreshMillis=900000 \
    --setParameter localLogicalSessionTimeoutMinutes=45 \
    --replSet rs0 --oplogSize 20480 --fork \
    --pidfilepath="$TEMP_PID_FILE"

# Wait for MongoDB to accept connections (up to 30 s)
echo "Waiting for MongoDB to accept connections on port ${_RS_PORT}..."
_wait=0
until $SNAP/bin/mongosh --port "${_RS_PORT}" --quiet \
        --eval "db.adminCommand({ping:1})" >/dev/null 2>&1; do
    _wait=$((_wait + 1))
    if [ $_wait -ge 30 ]; then
        echo "WARNING: MongoDB did not respond within 30 seconds"
        break
    fi
    sleep 1
done

# Check replica set status and current member host
_rs_check=$($SNAP/bin/mongosh --port "${_RS_PORT}" --quiet --eval "
    try {
        var s = rs.status();
        var c = rs.conf();
        print('OK:' + c.members[0].host);
    } catch(e) {
        print('ERROR:' + e.message);
    }
" 2>/dev/null)
echo "Replica set check: ${_rs_check}"

if echo "$_rs_check" | grep -q "^OK:"; then
    _current_member=$(echo "$_rs_check" | sed 's/^OK://')
    if [ "$_current_member" != "$RS_MEMBER_HOST" ]; then
        echo "Member host mismatch: current='${_current_member}', expected='${RS_MEMBER_HOST}'. Reconfiguring..."
        $SNAP/bin/mongosh --port "${_RS_PORT}" --eval "
            try {
                rs.reconfig({_id:'rs0', members:[{_id:0, host:'${RS_MEMBER_HOST}'}]}, {force:true});
                print('Replica set reconfigured successfully.');
            } catch(e) { print('Reconfig error: ' + e.message); }
        " 2>/dev/null || true
    else
        echo "Replica set config is valid."
    fi
else
    # Not initialized or config is invalid — try initiate first, then reconfig
    echo "Replica set not ready. Initializing with member: ${RS_MEMBER_HOST}..."
    $SNAP/bin/mongosh --port "${_RS_PORT}" --eval "
        try {
            rs.initiate({_id:'rs0', members:[{_id:0, host:'${RS_MEMBER_HOST}'}]});
            print('Replica set initialized.');
        } catch(e) {
            try {
                rs.reconfig({_id:'rs0', members:[{_id:0, host:'${RS_MEMBER_HOST}'}]}, {force:true});
                print('Replica set reconfigured.');
            } catch(e2) { print('Error: ' + e2.message); }
        }
    " 2>/dev/null || true
fi

# Ensure init marker exists regardless of path taken above
[ -f "$INIT_MARKER" ] || touch "$INIT_MARKER"

# Shut down the temporary MongoDB process using its PID file so we only
# kill this instance and never another parallel snap's mongod.
echo "Stopping temporary MongoDB process..."
$SNAP/bin/mongosh --port "${_RS_PORT}" --eval \
    "db.getSiblingDB('admin').shutdownServer()" 2>/dev/null || true
sleep 2
if [ -f "$TEMP_PID_FILE" ]; then
    kill "$(cat "$TEMP_PID_FILE")" 2>/dev/null || true
    rm -f "$TEMP_PID_FILE"
fi
sleep 1

# Final start of MongoDB in foreground (this becomes the main process)
exec $SNAP/bin/mongod \
    --dbpath="$MONGO_DATA_DIR" \
    --logpath="$MONGO_LOG_FILE" \
    --logappend $BIND_OPTIONS \
    --storageEngine wiredTiger --wiredTigerCacheSizeGB 32 \
    --timeZoneInfo /usr/share/zoneinfo \
    --setParameter logicalSessionRefreshMillis=900000 \
    --setParameter localLogicalSessionTimeoutMinutes=45 \
    --replSet rs0 --oplogSize 20480
