#!/bin/bash

set -u

umask 077

if [[ -z "${APPDIR:-}" ]]; then
    echo "Komp AC: APPDIR is not set by the AppImage runtime" >&2
    exit 1
fi

data_home="${XDG_DATA_HOME:-${HOME:?HOME is not set}/.local/share}"
data_root="${KOMP_AC_DATA_DIR:-$data_home/komp_ac}"
postgres_root="$data_root/postgresql"
dump_root="$data_root/dumps"
tantivy_root="$data_root/tantivy_indexes"
secret_file="$data_root/jwt.secret"
log_file="$data_root/server.log"
lock_dir="$data_root/appimage.lock"
server="$APPDIR/usr/bin/komp-ac-server"
gui="$APPDIR/AppRun.gui"
server_db_mode_file="$APPDIR/usr/share/komp-ac/server-db-mode"

if [[ ! -r "$server_db_mode_file" ]]; then
    echo "Komp AC: bundled server database mode is missing" >&2
    exit 1
fi
server_db_mode="$(<"$server_db_mode_file")"
if [[ "$server_db_mode" != embedded && "$server_db_mode" != external ]]; then
    echo "Komp AC: invalid bundled server database mode: $server_db_mode" >&2
    exit 1
fi

mkdir -p "$data_root" "$postgres_root" "$dump_root" "$tantivy_root"

if [[ ! -s "$secret_file" ]]; then
    secret_tmp="$secret_file.$$"
    if ! od -An -N 48 -tx1 /dev/urandom | tr -d ' \n' > "$secret_tmp"; then
        rm -f -- "$secret_tmp"
        echo "Komp AC: could not generate the local server secret" >&2
        exit 1
    fi
    chmod 600 "$secret_tmp"
    if [[ -e "$secret_file" ]]; then
        rm -f -- "$secret_tmp"
    else
        mv -- "$secret_tmp" "$secret_file"
    fi
fi

if ! mkdir "$lock_dir" 2>/dev/null; then
    lock_pid=""
    if [[ -r "$lock_dir/pid" ]]; then
        read -r lock_pid < "$lock_dir/pid" || true
    fi
    if [[ "$lock_pid" =~ ^[0-9]+$ ]] && kill -0 "$lock_pid" 2>/dev/null; then
        echo "Komp AC is already running (launcher PID $lock_pid)." >&2
        exit 1
    fi
    rm -f -- "$lock_dir/pid"
    if ! rmdir "$lock_dir" 2>/dev/null || ! mkdir "$lock_dir" 2>/dev/null; then
        echo "Komp AC: could not acquire the application lock at $lock_dir" >&2
        exit 1
    fi
fi
printf '%s\n' "$$" > "$lock_dir/pid"

server_pid=""
cleanup() {
    status=$?
    trap - EXIT INT TERM HUP
    if [[ -n "$server_pid" ]] && kill -0 "$server_pid" 2>/dev/null; then
        kill -TERM "$server_pid" 2>/dev/null || true
        wait "$server_pid" 2>/dev/null || true
    fi
    rm -f -- "$lock_dir/pid"
    rmdir "$lock_dir" 2>/dev/null || true
    exit "$status"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
trap 'exit 129' HUP

export GRPC_ENDPOINT="http://127.0.0.1:50051"

if (exec 3<>/dev/tcp/127.0.0.1/50051) 2>/dev/null; then
    echo "Komp AC: local port 50051 is already in use" >&2
    exit 1
fi

RUST_DB_MODE="$server_db_mode" \
KOMP_AC_POSTGRES_DIR="$postgres_root" \
PG_DUMP_DIR="$dump_root" \
TANTIVY_INDEX_DIR="$tantivy_root" \
JWT_SECRET="$(<"$secret_file")" \
GRPC_LISTEN_ADDRESS="127.0.0.1:50051" \
"$server" server >> "$log_file" 2>&1 &
server_pid=$!

ready=false
for ((attempt = 0; attempt < 600; attempt++)); do
    if ! kill -0 "$server_pid" 2>/dev/null; then
        wait "$server_pid" || true
        echo "Komp AC: the bundled server failed to start; see $log_file" >&2
        exit 1
    fi
    if (exec 3<>/dev/tcp/127.0.0.1/50051) 2>/dev/null; then
        ready=true
        break
    fi
    sleep 0.1
done

if [[ "$ready" != true ]]; then
    echo "Komp AC: the bundled server did not become ready; see $log_file" >&2
    exit 1
fi

"$gui"
