#!/usr/bin/env sh
# TUI gate: build, vet, test, and assert the CLI and PTY-shell contracts.
#
# Run from anywhere. CI runs this directly (see .github/workflows/tui.yml),
# and the root bin/test calls it when go is on PATH.
set -eu

ROOT="$(CDPATH= cd -- "$(dirname -- "$0")/../.." && pwd)"
TUI="$ROOT/tui"
cd "$TUI"

# The shared conventions gate carries the TUI checks too (the internal/irc
# platform-neutrality rule). Run it here so a TUI-only change is fully gated by
# tui.yml without the Qt workflow rebuilding the app. The root bin/test exports
# OMAIRC_CONVENTIONS_RAN after it runs the gate, so it is not run twice.
if [ "${OMAIRC_CONVENTIONS_RAN:-}" != "1" ]; then
  "$ROOT/bin/check-conventions"
fi

if ! command -v go >/dev/null 2>&1; then
  echo "go is required to test omairc-tui." >&2
  exit 1
fi

# Build before vet/test: internal/gate.TestPTYSmokeDemoShell only runs when
# tui/bin/omairc-tui exists and is a shell build, so the freshly built binary
# must be on disk. vet and test then still cover both binaries' packages.
"$TUI/bin/build"

go vet ./...
go test ./...

GOEXE="$(go env GOEXE)"
BIN="$TUI/bin/omairc-tui$GOEXE"

VERSION="$("$ROOT/bin/version")"
got="$("$BIN" --version)"
test "$got" = "omairc-tui $VERSION" || {
  echo "omairc-tui --version must print exactly omairc-tui $VERSION" >&2
  printf 'got: %s\n' "$got" >&2
  exit 1
}

assert_not_version_line() {
  first_line=$(printf '%s\n' "$1" | head -n 1)
  case "$first_line" in
    omairc-tui\ [0-9]*)
      echo "$2 printed the version line." >&2
      exit 1
      ;;
  esac
}

is_json_object() {
  case "$1" in
    \{*) return 0 ;;
    *) return 1 ;;
  esac
}

set +e
HELP_OUTPUT="$("$BIN" --help 2>&1)"
HELP_STATUS=$?
set -e
if [ "$HELP_STATUS" -ne 0 ]; then
  echo "omairc-tui --help failed." >&2
  exit 1
fi
assert_not_version_line "$HELP_OUTPUT" "omairc-tui --help"
if is_json_object "$HELP_OUTPUT"; then
  echo "omairc-tui --help must not print JSON." >&2
  exit 1
fi
for token in --version --help --demo-server; do
  printf '%s\n' "$HELP_OUTPUT" | grep -Fq -- "$token" || {
    echo "omairc-tui --help must mention $token" >&2
    exit 1
  }
done

# OMAIRC_BUILD_VERSION must override version.pri, matching the Qt contract.
OVERRIDE_VERSION="${VERSION}+main.gdeadbeef"
OMAIRC_BUILD_VERSION="$OVERRIDE_VERSION" "$TUI/bin/build"
override_got="$("$BIN" --version)"
test "$override_got" = "omairc-tui $OVERRIDE_VERSION" || {
  echo "OMAIRC_BUILD_VERSION must appear in omairc-tui --version" >&2
  printf 'got: %s\n' "$override_got" >&2
  exit 1
}

# Leave the tree with a normal build.
"$TUI/bin/build"

# Host-arch static archive. A dynamic link or a missed ldflag fails the gate.
"$TUI/bin/package"
host_os="$(go env GOHOSTOS)"
host_arch="$(go env GOHOSTARCH)"
case "$host_os" in
  windows) archive_ext=zip ;;
  *) archive_ext=tar.gz ;;
esac
archive="$TUI/dist/omairc-tui-${VERSION}-${host_os}-${host_arch}.${archive_ext}"
test -f "$archive" || {
  echo "missing static archive $archive" >&2
  exit 1
}

# install-tui.sh installs the archive the package step just built, offline.
# Windows has no POSIX uname path, so the installer skips it there.
case "$host_os" in
  windows)
    echo "Skipping the install-tui.sh check on Windows." >&2
    ;;
  *)
    install_dir="$(mktemp -d "${TMPDIR:-/tmp}/omairc-tui-install.XXXXXX")"
    OMAIRC_TUI_VERSION="$VERSION" \
    OMAIRC_TUI_DOWNLOAD_URL="file://$archive" \
    OMAIRC_TUI_BIN_DIR="$install_dir" \
      "$ROOT/install-tui.sh"
    installed="$("$install_dir/omairc-tui" --version)"
    test "$installed" = "omairc-tui $VERSION" || {
      echo "install-tui.sh must install omairc-tui $VERSION" >&2
      printf 'got: %s\n' "$installed" >&2
      exit 1
    }
    rm -rf -- "$install_dir"
    ;;
esac

# PTY parity gate over the freshly built shell: launch it under a real PTY and
# assert the OSC title, the seeded sidebar text, and a rendered screenshot.
# Windows uses ConPTY (creack/pty) and AF_UNIX sockets on Win10+; the Linux
# matrix remains the primary gate when this runner is unavailable.
GATE="$TUI/bin/control-omairc-tui$GOEXE"
cleanup_gate() { "$GATE" cleanup >/dev/null 2>&1 || true; }
trap cleanup_gate EXIT INT TERM
cleanup_gate
"$GATE" launch --demo-server
"$GATE" doctor
"$GATE" wait-title --exact "#omarchy · irc.example · fred - Omairc"
title_got="$("$GATE" title)"
test "$title_got" = "#omarchy · irc.example · fred - Omairc" || {
  echo "shell title must be #omarchy · irc.example · fred - Omairc" >&2
  printf 'got: %s\n' "$title_got" >&2
  exit 1
}
"$GATE" screenshot --feature shell --name smoke
test -s "$ROOT/test-artifacts/verify-tui/shell/smoke.png" || {
  echo "missing screenshot $ROOT/test-artifacts/verify-tui/shell/smoke.png" >&2
  exit 1
}
# Assert the seeded sidebar rows through the daemon's reconstructed grid text.
grid="$("$GATE" text)"
for token in '#omarchy' '#ricing' anna dax; do
  printf '%s\n' "$grid" | grep -Fq -- "$token" || {
    echo "shell grid text must mention $token" >&2
    exit 1
  }
done
cleanup_gate
