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

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "${ROOT}"

tmp_dir="$(mktemp -d)"
pick_port() {
  python - <<'PY'
import socket

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
    sock.bind(("127.0.0.1", 0))
    print(sock.getsockname()[1])
PY
}

release_id="release-$$"
export CONTEXT_KIT_COMPOSE_PROJECT="context-kit-${release_id}"
export CONTEXT_KIT_DATA_DIR="${tmp_dir}/data"
export CONTEXT_KIT_PROJECT_DIR="${ROOT}"
export CONTEXT_KIT_SEARXNG_PORT="$(pick_port)"
export CONTEXT_KIT_DOCS_PORT="$(pick_port)"
export CONTEXT_KIT_DOCS_LOCAL_SOURCES_DIR="${tmp_dir}/local-sources"
export CONTEXT_KIT_DOCS_LOCAL_SOURCES_PORT="8769"
local_sources_profile="${tmp_dir}/sources.local.txt"
export CONTEXT_KIT_DOCS_SOURCES="config/sources.default.txt ${local_sources_profile}"
export CONTEXT_KIT_LOCAL_SOURCE_SMOKE_URL="http://127.0.0.1:${CONTEXT_KIT_DOCS_LOCAL_SOURCES_PORT}/release-fixture/llms.txt"
export CONTEXT_KIT_WEB_SEARCH_IMAGE="context-kit/web-search-mcp:${release_id}"
export CONTEXT_KIT_DOCS_IMAGE="context-kit/docs-mcp:${release_id}"

mkdir -p "${CONTEXT_KIT_DOCS_LOCAL_SOURCES_DIR}/release-fixture"
printf '%s\n' \
  '# Release Check Local Source' \
  '' \
  '> Exercises machine-local llms.txt serving and refresh behavior.' \
  '' \
  '## MCP' \
  '' \
  '- [Model Context Protocol](https://modelcontextprotocol.io/)' \
  > "${CONTEXT_KIT_DOCS_LOCAL_SOURCES_DIR}/release-fixture/llms.txt"
printf '%s\n' "${CONTEXT_KIT_LOCAL_SOURCE_SMOKE_URL}" > "${local_sources_profile}"

cleanup() {
  docker compose -p "${CONTEXT_KIT_COMPOSE_PROJECT}" -f compose.yml down -v --remove-orphans >/dev/null 2>&1 || true
  docker image rm "${CONTEXT_KIT_WEB_SEARCH_IMAGE}" "${CONTEXT_KIT_DOCS_IMAGE}" >/dev/null 2>&1 || true
  rm -rf "${tmp_dir}"
}
trap cleanup EXIT

check_node() {
  local file
  for file in "$@"; do
    node --check "${file}"
  done
}

assert_redaction_check_does_not_disclose_matches() {
  local fixture="${tmp_dir}/redaction-fixture.txt"
  local output="${tmp_dir}/redaction-output.txt"
  local blocked_path="/data/proj""ects/context-kit-private-fixture"
  printf 'blocked=%s\n' "${blocked_path}" > "${fixture}"
  if bin/context-kit redaction-check "${fixture}" >"${output}" 2>&1; then
    printf 'redaction-check test unexpectedly passed\n' >&2
    return 1
  fi
  if grep -F "${blocked_path}" "${output}" >/dev/null; then
    printf 'redaction-check disclosed matched content\n' >&2
    return 1
  fi
}

assert_web_search_image() {
  docker run --rm --entrypoint node \
    -e EXPECTED_MAX_BYTES="${CONTEXT_KIT_WEB_SEARCH_MAX_BYTES:-52428800}" \
    "${CONTEXT_KIT_WEB_SEARCH_IMAGE}" \
    -e '
const fs = require("node:fs");
const expected = Number(process.env.EXPECTED_MAX_BYTES) || 0;
const actual = Number(process.env.MAX_BYTES) || 0;
if (process.getuid && process.getuid() === 0) process.exit(1);
if (actual !== expected) process.exit(1);

const serverPath = "/usr/local/lib/node_modules/@zhafron/mcp-web-search/dist/src/server.js";
const server = fs.readFileSync(serverPath, "utf8");
if (!server.includes("max_download_bytes: z.number().int().min(1).max(MAX_BYTES).optional()")) process.exit(1);

const bingPath = "/usr/local/lib/node_modules/@zhafron/mcp-web-search/dist/src/providers/bing.js";
const bing = fs.readFileSync(bingPath, "utf8");
if (!bing.includes("Context Kit override for @zhafron/mcp-web-search 1.3.0")) process.exit(1);
if (!bing.includes("waitForSelector")) process.exit(1);
if (!bing.includes("decodeBingRedirect")) process.exit(1);
' >/dev/null

  docker run --rm --entrypoint /usr/bin/test \
    "${CONTEXT_KIT_WEB_SEARCH_IMAGE}" \
    -x "${CONTEXT_KIT_WEB_SEARCH_CHROME_PATH:-/usr/bin/chromium}"
}

git diff --check HEAD
git show --check --format= HEAD >/dev/null
git ls-files --cached --error-unmatch \
  docker/web-search/patch-mcp-web-search.mjs \
  docker/web-search/overrides/bing.js \
  docker/docs/constraints.txt \
  scripts/mcp-smoke-client.mjs \
  scripts/smoke-web-search.mjs \
  scripts/smoke-docs.mjs \
  scripts/smoke-repomix.mjs \
  scripts/release-check >/dev/null
bash -n bin/context-kit
bash -n scripts/release-check
sh -n docker/docs/entrypoint.sh
check_node docker/web-search/patch-mcp-web-search.mjs docker/web-search/overrides/bing.js scripts/mcp-smoke-client.mjs scripts/smoke-web-search.mjs scripts/smoke-docs.mjs scripts/smoke-repomix.mjs

node -e 'const fs=require("node:fs"); JSON.parse(fs.readFileSync("snippets/opencode.json", "utf8")); JSON.parse(fs.readFileSync("snippets/claude.mcp.json", "utf8"));'
CONTEXT_KIT_DOCS_HTTP_URL="http://127.0.0.1:8776/mcp" bin/context-kit install opencode > "${tmp_dir}/opencode-default.json"
cmp -s snippets/opencode.json "${tmp_dir}/opencode-default.json" || {
  printf 'snippets/opencode.json differs from bin/context-kit install opencode output\n' >&2
  diff -u snippets/opencode.json "${tmp_dir}/opencode-default.json" >&2 || true
  exit 1
}
CONTEXT_KIT_DOCS_HTTP_URL="http://127.0.0.1:8776/mcp" bin/context-kit install claude > "${tmp_dir}/claude-default.json"
cmp -s snippets/claude.mcp.json "${tmp_dir}/claude-default.json" || {
  printf 'snippets/claude.mcp.json differs from bin/context-kit install claude output\n' >&2
  diff -u snippets/claude.mcp.json "${tmp_dir}/claude-default.json" >&2 || true
  exit 1
}
bin/context-kit install opencode > "${tmp_dir}/opencode.json"
bin/context-kit install opencode --absolute > "${tmp_dir}/opencode-absolute.json"
bin/context-kit install claude > "${tmp_dir}/claude.json"
bin/context-kit install claude --absolute > "${tmp_dir}/claude-absolute.json"
node -e 'const fs=require("node:fs"); for (const file of process.argv.slice(1)) JSON.parse(fs.readFileSync(file, "utf8"));' \
  "${tmp_dir}/opencode.json" \
  "${tmp_dir}/opencode-absolute.json" \
  "${tmp_dir}/claude.json" \
  "${tmp_dir}/claude-absolute.json"
bin/context-kit redaction-check "${tmp_dir}/opencode.json" "${tmp_dir}/claude.json"
assert_redaction_check_does_not_disclose_matches

bin/context-kit redaction-check
docker compose -p "${CONTEXT_KIT_COMPOSE_PROJECT}" -f compose.yml config >/dev/null
if env -u HOME -u CONTEXT_KIT_DATA_DIR -u CONTEXT_KIT_DOCS_LOCAL_SOURCES_DIR docker compose --env-file /dev/null -p context-kit-release-home-check -f compose.yml config >"${tmp_dir}/compose-no-home.out" 2>"${tmp_dir}/compose-no-home.err"; then
  printf 'compose config unexpectedly succeeded without HOME or CONTEXT_KIT_DATA_DIR\n' >&2
  exit 1
fi
CONTEXT_KIT_DATA_DIR="${tmp_dir}/compose-data" env -u HOME docker compose --env-file /dev/null -p context-kit-release-home-check -f compose.yml config >/dev/null
bin/context-kit build
assert_web_search_image
bin/context-kit restart
bin/context-kit doctor
node scripts/smoke-web-search.mjs bin/context-kit web-search
node scripts/smoke-docs.mjs bin/context-kit docs
node scripts/smoke-repomix.mjs bin/context-kit repomix

printf 'pass release-check\n'
