#!/bin/bash
# Multithreaded Deployment Script
# Builds natively on astra (aarch64), deploys to /opt/multithreaded.
# Run from the multithreaded project root.
#
# Usage:
#   ./deploy/deploy.sh              # Build + deploy + restart
#   ./deploy/deploy.sh --setup      # First-time: create user, dirs, db, build, install, seed

set -e

# Configuration
SERVER="max@100.106.221.39"
REMOTE_DIR="/opt/multithreaded"
SRC_DIR="src/multithreaded"
BINARY_NAME="multithreaded"
DEPLOY_DIR="deploy"

# Check we're in the right directory
if [ ! -f "Cargo.toml" ] || ! grep -q 'name = "multithreaded"' Cargo.toml; then
    echo "Error: Run this script from the MNW/multithreaded/ directory"
    exit 1
fi

rsync_source() {
    echo "[rsync] Uploading source to $SERVER:~/$SRC_DIR/..."
    ssh $SERVER "mkdir -p ~/$SRC_DIR"
    # node_modules is reinstalled on the build host by build.rs (npm ci) and is
    # large, platform-specific, and regenerable. static/dist is NOT excluded:
    # it is emitted there by the same build script during cargo build.
    rsync -az --delete \
        --exclude target/ \
        --exclude .env \
        --exclude .git/ \
        --exclude frontend/node_modules/ \
        ./ $SERVER:~/$SRC_DIR/

    # Sync the sibling crates the manifests point at (`../shared/...` resolves
    # the same way from ~/src/multithreaded on the build host).
    #
    # Read the list out of the manifests rather than hardcoding it. The hardcoded
    # version listed docengine and livechat, which mt no longer takes by path,
    # and omitted pom-contract, which it does: the build failed on the build host
    # for a dependency the deploy script had never heard of. A list derived from
    # the manifests cannot drift from them.
    local dep_paths dep_path dep
    dep_paths="$(grep -ho 'path = "\.\./[^"]*"' Cargo.toml crates/*/Cargo.toml \
        | sed 's/path = "//; s/"$//' | sort -u)"
    for dep_path in $dep_paths; do
        dep="${dep_path#../}"
        if [ -d "$dep_path" ]; then
            echo "[rsync] Syncing sibling crate: $dep"
            ssh $SERVER "mkdir -p ~/src/$dep"
            rsync -az --delete --exclude target --exclude .git \
                "$dep_path/" "$SERVER:~/src/$dep/"
        else
            echo "[rsync] ERROR: manifest points at $dep_path, which does not exist" >&2
            exit 1
        fi
    done
    echo "[rsync] Done"
}

build_remote() {
    echo "[build] Building release on astra..."
    ssh $SERVER "cd ~/$SRC_DIR && ~/.cargo/bin/cargo build --release 2>&1"
    echo "[build] Done"
}

# static/ is deliberately not copied: it is compiled into the binary
# (src/static_assets.rs), so the binary IS the assets. migrations/ is copied for
# operator convenience only — sqlx::migrate!() embeds them at compile time too.
deploy_files() {
    echo "[deploy] Stopping service + copying binary to $REMOTE_DIR..."
    ssh $SERVER "
        sudo systemctl stop multithreaded || true
        sudo cp ~/$SRC_DIR/target/release/$BINARY_NAME $REMOTE_DIR/$BINARY_NAME
        sudo chmod +x $REMOTE_DIR/$BINARY_NAME
        sudo rsync -a --delete ~/$SRC_DIR/migrations/ $REMOTE_DIR/migrations/
        sudo chown -R multithreaded:multithreaded $REMOTE_DIR
    "
    echo "[deploy] Done"
}

restart_app() {
    echo "[restart] Restarting multithreaded..."
    ssh $SERVER "sudo systemctl restart multithreaded"
    sleep 2
    echo ""
    ssh $SERVER "sudo systemctl status multithreaded --no-pager"
    echo ""
    echo "[health] Checking..."
    ssh $SERVER "curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1:3400/"
}

first_time_setup() {
    echo "=== First-Time Setup ==="

    echo "[setup] Creating system user..."
    ssh $SERVER "
        sudo useradd --system --shell /usr/sbin/nologin --home-dir $REMOTE_DIR multithreaded 2>/dev/null || echo 'User already exists'
    "

    echo "[setup] Creating directories..."
    ssh $SERVER "
        sudo mkdir -p $REMOTE_DIR
        sudo chown multithreaded:multithreaded $REMOTE_DIR
    "

    echo "[setup] Creating database role + database..."
    ssh $SERVER "
        sudo -u postgres createuser multithreaded 2>/dev/null || echo 'Role already exists'
        createdb multithreaded 2>/dev/null || echo 'Database already exists'
        sudo -u postgres psql -c 'GRANT ALL PRIVILEGES ON DATABASE multithreaded TO multithreaded;' 2>/dev/null
        sudo -u postgres psql -d multithreaded -c 'GRANT ALL ON SCHEMA public TO multithreaded;' 2>/dev/null
    "

    rsync_source
    build_remote

    echo "[setup] Installing files..."
    deploy_files

    echo "[setup] Installing env file..."
    ssh $SERVER "
        sudo cp ~/$SRC_DIR/$DEPLOY_DIR/env.production $REMOTE_DIR/.env
        sudo chmod 600 $REMOTE_DIR/.env
        sudo chown multithreaded:multithreaded $REMOTE_DIR/.env
    "

    echo "[setup] Installing systemd service..."
    ssh $SERVER "
        sudo cp ~/$SRC_DIR/$DEPLOY_DIR/multithreaded.service /etc/systemd/system/multithreaded.service
        sudo systemctl daemon-reload
        sudo systemctl enable multithreaded
    "

    echo "[setup] Starting service..."
    ssh $SERVER "sudo systemctl start multithreaded"
    sleep 2

    echo "[setup] Running seed..."
    ssh $SERVER "
        cd $REMOTE_DIR
        sudo -u multithreaded $REMOTE_DIR/$BINARY_NAME --seed
    "

    echo ""
    ssh $SERVER "sudo systemctl status multithreaded --no-pager"
    echo ""
    echo "[health] Checking..."
    ssh $SERVER "curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1:3400/"
}

case "${1:-deploy}" in
    --setup)
        first_time_setup
        ;;
    deploy|"")
        echo "=== Deploy ==="
        rsync_source
        build_remote
        deploy_files
        restart_app
        ;;
    *)
        echo "Usage: $0 [--setup]"
        exit 1
        ;;
esac

echo ""
echo "=== Done ==="
