#!/bin/bash
# Makenotwork Deployment Script
# Cross-compiles for x86_64 Linux on macOS, uploads everything, restarts services.
# Run from the MNW/server directory.
#
# Usage:
#   ./deploy/deploy.sh              # Full deploy (build + upload + config + restart)
#   ./deploy/deploy.sh --quick      # Quick deploy (build + upload binary + restart app)
#   ./deploy/deploy.sh --config     # Config only (upload Caddyfile, systemd, error pages, backup script)
#
# Prerequisites (one-time):
#   brew install zig
#   cargo install cargo-zigbuild
#   rustup target add x86_64-unknown-linux-gnu

set -e

# Configuration
SERVER="root@100.120.174.96"
SSH_PORT=2200
SSH_OPTS="-p $SSH_PORT"
SCP_OPTS="-P $SSH_PORT"
REMOTE_DIR="/opt/makenotwork"
BINARY_NAME="makenotwork"
TARGET="x86_64-unknown-linux-gnu"
DEPLOY_DIR="deploy"

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

upload_config() {
    echo "[config] Uploading configuration files..."
    scp $SCP_OPTS $DEPLOY_DIR/Caddyfile $SERVER:/etc/caddy/Caddyfile
    scp $SCP_OPTS $DEPLOY_DIR/makenotwork.service $SERVER:/etc/systemd/system/makenotwork.service
    scp $SCP_OPTS $DEPLOY_DIR/backup-db.sh $SERVER:$REMOTE_DIR/backup-db.sh
    ssh $SSH_OPTS $SERVER "chmod +x $REMOTE_DIR/backup-db.sh"

    # Error pages
    ssh $SSH_OPTS $SERVER "mkdir -p $REMOTE_DIR/error-pages"
    scp $SCP_OPTS $DEPLOY_DIR/error-pages/*.html $SERVER:$REMOTE_DIR/error-pages/

    # Git SSH and security config files
    ssh $SSH_OPTS $SERVER "mkdir -p $REMOTE_DIR/deploy"
    scp $SCP_OPTS $DEPLOY_DIR/sshd-git.conf $DEPLOY_DIR/fail2ban-sshd.conf $DEPLOY_DIR/setup-firewall.sh $SERVER:$REMOTE_DIR/deploy/
    scp $SCP_OPTS $DEPLOY_DIR/setup-git-ssh.sh $DEPLOY_DIR/setup-ssh-keys.sh $SERVER:$REMOTE_DIR/deploy/ 2>/dev/null || true
    # Scan-pipeline setup scripts (one-time, manually run on prod). See
    # docs/scan-pipeline-audit.md § 8 for the rollout procedure.
    scp $SCP_OPTS $DEPLOY_DIR/setup-clamav.sh $DEPLOY_DIR/setup-yara-rules.sh $SERVER:$REMOTE_DIR/deploy/
    ssh $SSH_OPTS $SERVER "chmod +x $REMOTE_DIR/deploy/setup-firewall.sh $REMOTE_DIR/deploy/setup-git-ssh.sh $REMOTE_DIR/deploy/setup-ssh-keys.sh $REMOTE_DIR/deploy/setup-clamav.sh $REMOTE_DIR/deploy/setup-yara-rules.sh 2>/dev/null || true"

    # Minify CSS for production (restore source on exit)
    echo "[config] Minifying CSS..."
    cp static/style.css static/style.css.src
    restore_css() { [ -f static/style.css.src ] && mv static/style.css.src static/style.css; }
    trap restore_css EXIT
    npx --yes clean-css-cli -o static/style.css static/style.css.src
    echo "[config] CSS: $(wc -c < static/style.css.src | tr -d ' ')B -> $(wc -c < static/style.css | tr -d ' ')B"

    # Static assets (CSS, JS, fonts, images)
    echo "[config] Uploading static assets..."
    rsync -az --delete static/ $SERVER:$REMOTE_DIR/static/

    # Restore unminified CSS
    restore_css
    trap - EXIT

    # Documentation (public markdown files + UI examples)
    echo "[config] Uploading documentation..."
    rsync -az --delete site-docs/public/ $SERVER:$REMOTE_DIR/docs/public/
    rsync -az --delete site-docs/examples/ $SERVER:$REMOTE_DIR/docs/examples/

    # Business assumptions (source-of-truth for substituted figures in docs)
    # Lives in the private docs store outside the repo (moved 2026-05-20).
    rsync -az docs/business/assumptions.toml $SERVER:$REMOTE_DIR/docs/assumptions.toml

    # Rustdoc (API reference for library crates)
    echo "[config] Generating rustdoc..."
    "$DEPLOY_DIR/generate-rustdoc.sh"
    echo "[config] Uploading rustdoc..."
    rsync -az --delete rustdoc-out/ $SERVER:$REMOTE_DIR/rustdoc/

    # Reload systemd and restart Caddy
    ssh $SSH_OPTS $SERVER "systemctl daemon-reload && systemctl restart caddy"
    echo "[config] Done"
}

build_binary() {
    echo "[build] Cross-compiling for $TARGET..."
    ulimit -n 65536 2>/dev/null || true
    cargo zigbuild --release --target $TARGET
    echo "[build] Done: target/$TARGET/release/$BINARY_NAME"
}

upload_binary() {
    echo "[upload] Stopping service and uploading binary..."
    ssh $SSH_OPTS $SERVER "systemctl stop makenotwork || true"
    scp $SCP_OPTS target/$TARGET/release/$BINARY_NAME $SERVER:$REMOTE_DIR/$BINARY_NAME
    ssh $SSH_OPTS $SERVER "chmod +x $REMOTE_DIR/$BINARY_NAME"
    # Also upload mnw-admin binary (used for SSH key management)
    if [ -f "target/$TARGET/release/mnw-admin" ]; then
        scp $SCP_OPTS target/$TARGET/release/mnw-admin $SERVER:$REMOTE_DIR/mnw-admin
        ssh $SSH_OPTS $SERVER "chmod +x $REMOTE_DIR/mnw-admin"
        echo "[upload] mnw-admin binary uploaded"
    fi
    echo "[upload] Done"
}

send_restart_warning() {
    echo "[warning] Sending 30s restart warning to users..."
    local token
    token=$(ssh $SSH_OPTS $SERVER "grep '^CLI_SERVICE_TOKEN=' $REMOTE_DIR/.env 2>/dev/null | cut -d= -f2-" | tr -d '\r\n')
    if [ -z "$token" ]; then
        echo "[warning] CLI_SERVICE_TOKEN not found in .env, skipping warning"
        return 0
    fi
    local status
    status=$(ssh $SSH_OPTS $SERVER "curl -s -o /dev/null -w '%{http_code}' -X POST http://127.0.0.1:3000/api/internal/restart-warning -H 'Authorization: Bearer $token' -H 'Content-Type: application/json' -d '{\"seconds\": 30}'")
    if [ "$status" = "204" ]; then
        echo "[warning] Restart warning sent, waiting 30s..."
        sleep 30
    else
        echo "[warning] Warning request returned HTTP $status, continuing without delay"
    fi
}

restart_app() {
    echo "[restart] Restarting makenotwork..."
    ssh $SSH_OPTS $SERVER "systemctl restart makenotwork"
    sleep 1
    echo ""
    ssh $SSH_OPTS $SERVER "systemctl status makenotwork --no-pager"
    echo ""
    echo "[restart] Verifying app responds..."
    ssh $SSH_OPTS $SERVER "curl -s -o /dev/null -w 'HTTP %{http_code}\n' http://127.0.0.1:3000"
}

case "${1:-full}" in
    --quick)
        echo "=== Quick Deploy ==="
        build_binary
        send_restart_warning
        upload_binary
        restart_app
        ;;
    --config)
        echo "=== Config Deploy ==="
        upload_config
        ;;
    full|"")
        echo "=== Full Deploy ==="
        build_binary
        upload_config
        send_restart_warning
        upload_binary
        restart_app
        ;;
    *)
        echo "Usage: $0 [--quick|--config]"
        exit 1
        ;;
esac

echo ""
echo "=== Deploy Complete ==="
