#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR=$(cd -- "$(dirname -- "$0")" && pwd)
HOLDER="$SCRIPT_DIR/mosaic-tmux-holder.service"
AGENT="$SCRIPT_DIR/mosaic-agent@.service"
INTERACTION="$SCRIPT_DIR/mosaic-interaction-agent@.service"
HOLDER_START="$SCRIPT_DIR/../../tools/fleet/start-tmux-holder.sh"
START_AGENT="$SCRIPT_DIR/../../tools/fleet/start-agent-session.sh"

fail() {
  echo "FAIL: $*" >&2
  exit 1
}

[ -f "$HOLDER" ] || fail "missing mosaic-tmux-holder.service"
[ -f "$AGENT" ] || fail "missing mosaic-agent@.service"
[ -f "$INTERACTION" ] || fail "missing mosaic-interaction-agent@.service"
[ -x "$HOLDER_START" ] || fail "missing executable start-tmux-holder.sh"
[ -x "$START_AGENT" ] || fail "missing executable start-agent-session.sh"

grep -qF 'ExecStart=' "$HOLDER" || fail "holder has no ExecStart"
grep -qF 'tmux -L' "$HOLDER" || fail "holder does not use named tmux socket"
grep -qF '_holder' "$HOLDER" || fail "holder session is not explicit"
grep -qF 'UnsetEnvironment=LD_PRELOAD BASH_ENV ENV' "$HOLDER" || \
  fail "holder does not remove loader and shell-control variables"
grep -qF 'ExecStart=/usr/bin/env -i HOME=%h PATH=/usr/bin:/bin MOSAIC_TMUX_SOCKET=mosaic-fleet MOSAIC_TMUX_HOLDER=_holder /bin/bash --noprofile --norc %h/.config/mosaic/tools/fleet/start-tmux-holder.sh' "$HOLDER" || \
  fail "holder does not clear manager environment before starting tmux"
grep -qF 'ExecStop=-/usr/bin/env -i HOME=%h PATH=/usr/bin:/bin MOSAIC_TMUX_SOCKET=mosaic-fleet /bin/bash --noprofile --norc -c' "$HOLDER" || \
  fail "holder stop does not clear manager environment"
if grep -qF -- '/bin/bash -lc' "$HOLDER"; then
  fail "holder must not start tmux through a login shell"
fi
grep -qF 'Requires=mosaic-tmux-holder.service' "$AGENT" || fail "agent does not require holder"
grep -qF 'start-agent-session.sh' "$AGENT" || fail "agent unit does not call start-agent-session.sh"
if grep -qE '^Environment(File)?=' "$AGENT" "$INTERACTION"; then
  fail "agent units must not accept ambient or projection environment before strict parsing"
fi
grep -qF 'UnsetEnvironment=LD_PRELOAD BASH_ENV ENV' "$AGENT" || \
  fail "agent unit does not remove loader and shell-control variables"
grep -qF 'UnsetEnvironment=LD_PRELOAD BASH_ENV ENV' "$INTERACTION" || \
  fail "interaction unit does not remove loader and shell-control variables"
grep -qF 'ExecStart=/usr/bin/env -i HOME=%h MOSAIC_AGENT_NAME=%i PATH=/usr/bin:/bin /bin/bash --noprofile --norc' "$AGENT" || \
  fail "agent unit does not clear bootstrap environment before strict parsing"
grep -qF 'start-agent-session.sh --stop %i' "$AGENT" || \
  fail "agent stop does not use the validated exact-stop path"
grep -qF 'Requires=mosaic-tmux-holder.service' "$INTERACTION" || fail "interaction service does not require holder"
grep -qF 'ExecStart=/usr/bin/env -i HOME=%h MOSAIC_AGENT_NAME=%i PATH=/usr/bin:/bin /bin/bash --noprofile --norc' "$INTERACTION" || \
  fail "interaction unit does not clear bootstrap environment before strict parsing"
grep -qF 'start-interaction-service.sh %i' "$INTERACTION" || fail "interaction service does not use shared strict parsing"
grep -qF 'start-agent-session.sh --stop %i' "$INTERACTION" || \
  fail "interaction stop does not use the validated exact-stop path"

if command -v systemd-analyze >/dev/null 2>&1; then
  systemd-analyze verify --user "$HOLDER" "$AGENT" "$INTERACTION" >/tmp/mosaic-fleet-systemd-verify.log 2>&1 || {
    cat /tmp/mosaic-fleet-systemd-verify.log >&2
    fail "systemd-analyze verify failed"
  }
fi

# Real isolated socket regression: a preexisting server with an LD_PRELOAD
# constructor marker must fail closed, while a fresh named server is created.
if command -v tmux >/dev/null 2>&1 && command -v cc >/dev/null 2>&1; then
  TEST_ROOT=$(mktemp -d)
  TEST_SOCKET="mosaic-holder-test-$$"
  trap 'tmux -L "$TEST_SOCKET" kill-server >/dev/null 2>&1 || true; rm -rf "$TEST_ROOT"' EXIT
  MARKER="$TEST_ROOT/loader-marker"
  LIBRARY="$TEST_ROOT/marker.so"
  HOLDER_HOME="$TEST_ROOT/holder-home"
  mkdir -p "$HOLDER_HOME/.config/mosaic/fleet/run"
  chmod 700 "$HOLDER_HOME/.config" "$HOLDER_HOME/.config/mosaic" \
    "$HOLDER_HOME/.config/mosaic/fleet" "$HOLDER_HOME/.config/mosaic/fleet/run"
  printf '123e4567-e89b-12d3-a456-426614174000\n' > \
    "$HOLDER_HOME/.config/mosaic/fleet/run/holder-owner"
  chmod 600 "$HOLDER_HOME/.config/mosaic/fleet/run/holder-owner"
  cat > "$TEST_ROOT/marker.c" <<'EOF'
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
__attribute__((constructor)) static void mark_loader(void) {
  const char *path = getenv("MOSAIC_LOADER_MARKER");
  if (path != NULL) {
    int fd = open(path, O_WRONLY | O_CREAT | O_APPEND, 0600);
    if (fd >= 0) { write(fd, "loaded\\n", 7); close(fd); }
  }
}
EOF
  cc -shared -fPIC -o "$LIBRARY" "$TEST_ROOT/marker.c"
  MOSAIC_LOADER_MARKER="$MARKER" LD_PRELOAD="$LIBRARY" \
    tmux -L "$TEST_SOCKET" new-session -d -s _holder 'sleep 60'
  [ -s "$MARKER" ] || fail "contaminated fixture did not execute loader constructor"
  server_pid=$(tmux -L "$TEST_SOCKET" display-message -p '#{pid}')
  : > "$MARKER"
  if /usr/bin/env -i HOME="$HOLDER_HOME" PATH=/usr/bin:/bin \
    MOSAIC_TMUX_SOCKET="$TEST_SOCKET" MOSAIC_TMUX_HOLDER=_holder "$HOLDER_START" \
    >"$TEST_ROOT/holder.out" 2>&1; then
    fail "holder adopted contaminated named server"
  fi
  grep -qF 'global environment does not match the owned-server contract' "$TEST_ROOT/holder.out" || \
    fail "holder did not report contaminated server environment"
  [ "$(tmux -L "$TEST_SOCKET" display-message -p '#{pid}')" = "$server_pid" ] || \
    fail "holder replaced a contaminated server instead of failing closed"
  [ ! -s "$MARKER" ] || fail "holder execution triggered a contaminated loader"

  # Agent validation must reject the same unmanaged server without cleaning its
  # global environment or adding a managed session.
  AGENT_HOME="$HOLDER_HOME/.config/mosaic"
  AGENT_NAME=loader-safe
  AGENT_WORKDIR="$AGENT_HOME/work"
  AGENT_BIN="$TEST_ROOT/agent-bin"
  mkdir -p "$AGENT_HOME/fleet/agents" "$AGENT_WORKDIR" "$AGENT_BIN"
  chmod 700 "$AGENT_HOME/fleet/agents"
  cat > "$AGENT_HOME/fleet/agents/$AGENT_NAME.env.generated" <<EOF
MOSAIC_AGENT_NAME=$AGENT_NAME
MOSAIC_AGENT_CLASS=code
MOSAIC_AGENT_RUNTIME=pi
MOSAIC_AGENT_MODEL=
MOSAIC_AGENT_REASONING=
MOSAIC_AGENT_TOOL_POLICY=code
MOSAIC_AGENT_WORKDIR=$AGENT_WORKDIR
MOSAIC_TMUX_SOCKET=$TEST_SOCKET
EOF
  printf 'MOSAIC_RUNTIME_BIN=%s\n' "$AGENT_BIN" > "$AGENT_HOME/fleet/agents/$AGENT_NAME.env.local"
  chmod 600 "$AGENT_HOME/fleet/agents/$AGENT_NAME.env.generated" \
    "$AGENT_HOME/fleet/agents/$AGENT_NAME.env.local"
  cat > "$AGENT_BIN/mosaic" <<'EOF'
#!/bin/sh
sleep 30
EOF
  chmod 700 "$AGENT_BIN/mosaic"
  server_environment_before=$(tmux -L "$TEST_SOCKET" show-environment -g | sort)
  server_sessions_before=$(tmux -L "$TEST_SOCKET" list-sessions | sort)
  if /usr/bin/env -i HOME="$HOLDER_HOME" PATH=/usr/bin:/bin MOSAIC_HOME="$AGENT_HOME" \
    "$START_AGENT" "$AGENT_NAME" >"$TEST_ROOT/agent.out" 2>&1; then
    fail "agent launcher adopted contaminated named server"
  fi
  [ "$(tmux -L "$TEST_SOCKET" display-message -p '#{pid}')" = "$server_pid" ] || \
    fail "agent launcher changed unmanaged server PID"
  [ "$(tmux -L "$TEST_SOCKET" show-environment -g | sort)" = "$server_environment_before" ] || \
    fail "agent launcher changed unmanaged global environment"
  [ "$(tmux -L "$TEST_SOCKET" list-sessions | sort)" = "$server_sessions_before" ] || \
    fail "agent launcher changed unmanaged sessions"
  tmux -L "$TEST_SOCKET" kill-server
  /usr/bin/env -i HOME="$HOLDER_HOME" PATH=/usr/bin:/bin \
    MOSAIC_TMUX_SOCKET="$TEST_SOCKET" MOSAIC_TMUX_HOLDER=_holder "$HOLDER_START"
  tmux -L "$TEST_SOCKET" has-session -t '=_holder:0.0' || fail "fresh holder was not created"
  if tmux -L "$TEST_SOCKET" show-environment -g LD_PRELOAD 2>/dev/null | grep -q '^LD_PRELOAD='; then
    fail "fresh holder retained LD_PRELOAD"
  fi
  /usr/bin/env -i HOME="$HOLDER_HOME" PATH=/usr/bin:/bin MOSAIC_HOME="$AGENT_HOME" \
    "$START_AGENT" "$AGENT_NAME"
  tmux -L "$TEST_SOCKET" has-session -t "=$AGENT_NAME:0.0" || \
    fail "agent did not launch on a valid owned server"
  tmux -L "$TEST_SOCKET" kill-server
  trap - EXIT
  rm -rf "$TEST_ROOT"
fi

echo "ok - fleet systemd unit templates"
