#!/usr/bin/env bash
# Sysadmin Chronicles — Launcher
# Usage: bash start-game.sh [--stop] [--manage-saves] [--reset-save]

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$SCRIPT_DIR"
SERVER_DIR="$PROJECT_ROOT/server"
FRONTEND_DIR="$PROJECT_ROOT/frontend"
DOMAIN="${SC_WORKSTATION_DOMAIN:-sc-workstation}"
NETWORK="${SC_NETWORK:-sc-internal}"
PORT="${PORT:-3000}"

export PORT
export LIBVIRT_DEFAULT_URI="${LIBVIRT_DEFAULT_URI:-qemu:///system}"

source "$PROJECT_ROOT/tools/lib/ui.sh"
source "$PROJECT_ROOT/tools/lib/config.sh"
source "$PROJECT_ROOT/tools/lib/save.sh"
source "$PROJECT_ROOT/tools/lib/internal-https.sh"

config_read || true
sc_ensure_internal_certs "$PROJECT_ROOT"
sc_export_internal_https_env

SERVER_PID=""
VIEWER_PID=""

_cleanup() {
    [ -n "$SERVER_PID" ] && kill "$SERVER_PID" 2>/dev/null || true
    [ -n "$VIEWER_PID" ] && kill "$VIEWER_PID" 2>/dev/null || true
}
trap '_cleanup' EXIT INT TERM

# ---------------------------------------------------------------------------
# Flag handling
# ---------------------------------------------------------------------------

for arg in "$@"; do
    case "$arg" in
        --stop)
            stopped=false
            for pid in $(sc_listen_pids "$PORT" || true); do
                if sc_pid_is_repo_server "$pid" "$PROJECT_ROOT"; then
                    sc_stop_pid "$pid"
                    stopped=true
                fi
            done
            if [ "$stopped" = true ]; then
                echo "  ✓ Game server stopped."
            else
                echo "  (no running game server found)"
            fi
            exit 0
            ;;
        --manage-saves)
            exec bash "$PROJECT_ROOT/tools/save/manage-saves.sh"
            ;;
        --reset-save)
            echo ""
            echo "  This will reset your current save to a new game."
            printf "  Type RESET to confirm: " >/dev/tty
            read -r _c </dev/tty
            echo ""
            if [ "$_c" = "RESET" ]; then
                save_reset
            else
                echo "  Cancelled."
            fi
            exit 0
            ;;
    esac
done

# ---------------------------------------------------------------------------
# Pre-flight checks
# ---------------------------------------------------------------------------

if ! command -v virsh >/dev/null 2>&1; then
    echo ""
    echo "  Your system is missing the virtual machine tools."
    echo "  Run install.sh to set up the game."
    echo ""
    exit 1
fi

if ! command -v node >/dev/null 2>&1; then
    echo ""
    echo "  Node.js is required but wasn't found."
    echo "  Run install.sh to set up the game."
    echo ""
    exit 1
fi

# Check images directory is accessible
SC_IMAGES_DIR="${SC_IMAGES_DIR:-}"
if [ -n "$SC_IMAGES_DIR" ] && [ ! -d "$SC_IMAGES_DIR" ]; then
    echo ""
    echo "  Can't find your game world."
    echo "  The VM images are stored at $SC_IMAGES_DIR"
    echo "  but that location isn't available right now."
    echo ""
    echo "  Is your game drive plugged in and mounted?"
    echo "  Once it's mounted, run start-game.sh again."
    echo ""
    exit 1
fi

# Check workstation domain exists
if ! virsh dominfo "$DOMAIN" >/dev/null 2>&1; then
    echo ""
    echo "  Your game world hasn't been built yet."
    echo "  Run install.sh to finish setup."
    echo ""
    exit 1
fi

# Check frontend has been built
if [ ! -f "$FRONTEND_DIR/dist/index.html" ]; then
    echo ""
    echo "  The game interface hasn't been built yet."
    echo "  Run install.sh to finish setup."
    echo ""
    exit 1
fi

# ---------------------------------------------------------------------------
# Ensure server dependencies are installed
# ---------------------------------------------------------------------------

if [ ! -d "$SERVER_DIR/node_modules" ]; then
    sc_info "Installing server dependencies..."
    (cd "$SERVER_DIR" && npm install --silent)
fi

# ---------------------------------------------------------------------------
# Start server if not already running
# ---------------------------------------------------------------------------

_server_ready() {
    ss -tlnp 2>/dev/null | grep -q ":${PORT} "
}

_ensure_server_port() {
    local pids=""
    pids="$(sc_listen_pids "$PORT" || true)"
    if [ -z "$pids" ]; then
        return 0
    fi

    local pid
    for pid in $pids; do
        if ! sc_pid_is_repo_server "$pid" "$PROJECT_ROOT"; then
            echo ""
            echo "  Port $PORT is already in use by another process (pid $pid)."
            echo "  Stop that process or set PORT to a free port before launching."
            echo ""
            exit 1
        fi
        if sc_pid_has_internal_tls "$pid"; then
            return 1
        fi
    done

    sc_info "Restarting game server with HTTPS enabled..."
    for pid in $pids; do
        sc_stop_pid "$pid"
    done
    return 0
}

_wait_for_server() {
    local timeout=15
    local i=0
    while ! _server_ready; do
        sleep 0.3
        (( i++ )) || true
        if [ "$i" -ge $(( timeout * 10 / 3 )) ]; then
            return 1
        fi
    done
}

if _ensure_server_port; then
    (
        cd "$SERVER_DIR"
        exec node src/index.js
    ) &
    SERVER_PID=$!
fi

# ---------------------------------------------------------------------------
# Ensure network is active
# ---------------------------------------------------------------------------

if virsh net-list --all 2>/dev/null | grep -q "\\b${NETWORK}\\b"; then
    if ! virsh net-info "$NETWORK" 2>/dev/null | grep -q "Active:.*yes"; then
        sc_info "Starting game network..."
        virsh net-start "$NETWORK" >/dev/null 2>&1 || true
    fi
fi

# ---------------------------------------------------------------------------
# Start workstation VM if not running
# ---------------------------------------------------------------------------

if [ "$(virsh domstate "$DOMAIN" 2>/dev/null | tr -d ' \n')" != "running" ]; then
    virsh start "$DOMAIN" >/dev/null 2>&1 || true
fi

# ---------------------------------------------------------------------------
# Wait for server, show startup status
# ---------------------------------------------------------------------------

if [ -n "$SERVER_PID" ] && ! _wait_for_server; then
    echo ""
    echo "  The game server didn't start in time."
    echo "  Check that port $PORT is available and try again."
    echo ""
    exit 1
fi

echo ""
sc_ok "Game server running"
sc_ok "Workstation online"
echo ""
echo "  Opening your desk..."
echo ""

# ---------------------------------------------------------------------------
# Open SPICE viewer (do not exec — we need to wait and then clean up)
# ---------------------------------------------------------------------------

_launch_viewer() {
    local spice_uri
    spice_uri="$(virsh domdisplay "$DOMAIN" 2>/dev/null | grep -i spice | head -n1 || true)"

    if [ -n "$spice_uri" ] && command -v remote-viewer >/dev/null 2>&1; then
        remote-viewer "$spice_uri" &
        VIEWER_PID=$!
    elif command -v virt-viewer >/dev/null 2>&1; then
        virt-viewer --connect "$LIBVIRT_DEFAULT_URI" "$DOMAIN" &
        VIEWER_PID=$!
    elif [ -n "$spice_uri" ] && command -v spicy >/dev/null 2>&1; then
        local port
        port="$(printf '%s' "$spice_uri" | grep -oE ':[0-9]+' | head -1 | tr -d ':')"
        spicy -h 127.0.0.1 -p "${port:-5900}" &
        VIEWER_PID=$!
    else
        echo "  No SPICE viewer found (virt-viewer or remote-viewer)."
        echo "  Run install.sh to set up the game."
        exit 1
    fi
}

_launch_viewer
wait "$VIEWER_PID" 2>/dev/null || true
