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

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

buf lint

assert_immutable_against_main() {
  local path="$1"
  if ! git cat-file -e "origin/main:$path" 2>/dev/null; then
    return
  fi

  local current_sha
  local base_sha
  current_sha="$(git hash-object "$path")"
  base_sha="$(git show "origin/main:$path" | git hash-object --stdin)"
  if [[ "$current_sha" != "$base_sha" ]]; then
    echo "immutable file changed against origin/main: $path" >&2
    exit 1
  fi
}

compatibility_baselines=(
  proto/compatibility/application-navigation-v1.binpb
  proto/compatibility/selected-root-v1.binpb
  proto/compatibility/record-access-v1.binpb
  proto/compatibility/record-mutation-v1.binpb
  proto/compatibility/identity-exchange-v1.binpb
  proto/compatibility/session-lifecycle-v1.binpb
  proto/compatibility/federated-login-v1.binpb
  proto/compatibility/authorization-lifecycle-v1.binpb
  proto/compatibility/record-query-v1.binpb
  proto/compatibility/related-counts-v1.binpb
  proto/compatibility/record-default-preview-v1.binpb
  proto/compatibility/recycle-bin-v1.binpb
  proto/compatibility/recycle-bin-mutation-v1.binpb
  proto/compatibility/record-view-v1.binpb
  proto/compatibility/record-attachment-sources-v1.binpb
  proto/compatibility/platform-api-v1.binpb
  proto/compatibility/effective-permissions-v1.binpb
  proto/compatibility/search-scope-order-v1.binpb
  proto/compatibility/approval-v1.binpb
  proto/compatibility/catalog-action-preview-v1.binpb
  proto/compatibility/application-result-v1.binpb
  proto/compatibility/outbound-intent-v1.binpb
  proto/compatibility/private-list-view-v1.binpb
  proto/compatibility/metadata-admin-read-v1.binpb
  proto/compatibility/bulk-ingest-v1.binpb
  proto/compatibility/approval-notification-flow-v1.binpb
  proto/compatibility/page-layout-resolution-v1.binpb
  proto/compatibility/permission-admin-v1.binpb
  proto/compatibility/analytics-authoring-v1.binpb
  proto/compatibility/analytics-authoring-report-v1.binpb
  proto/compatibility/resource-access-v1.binpb
  proto/compatibility/layout-authoring-v1.binpb
)

conformance_vectors=(
  pkg/runtime/delegationv1/testdata/ed25519-jws-v1.json
  pkg/runtime/recordaccessv1/conformance_vectors.json
  pkg/runtime/recordmutationv1/conformance_vectors.json
  pkg/runtime/recordmutationv1/use_case_digest_vector.json
  pkg/runtime/recordmutationv1/external_identity_digest_vector.json
  pkg/runtime/queryv1/conformance_vectors.json
  pkg/runtime/relatedcountsv1/conformance_vectors.json
  pkg/runtime/recyclebinv1/conformance_vectors.json
  pkg/runtime/recordviewv1/conformance_vectors.json
  pkg/catalogpublicationv1/conformance_vectors.json
  pkg/catalogpublicationv2/conformance_vectors.json
  pkg/runtime/servingbindingv1/conformance_vectors.json
  pkg/layoutbundlekeyv1/conformance_vectors.json
  pkg/layoutbundleownerverificationv1/conformance_vectors.json
  pkg/tenantlayoutbundleauthorityv1/conformance_vectors.json
  pkg/layoutroutingsecurityv1/conformance_vectors.json
  pkg/layoutactivationsetv1/conformance_vectors.json
  pkg/catalogassignmentidentityv1/conformance_vectors.json
  pkg/layoutvalidationviewv1/conformance_vectors.json
  pkg/applayoutbundleauthorityv1/conformance_vectors.json
  pkg/systemlayoutbundleauthorityv1/conformance_vectors.json
)

for immutable_path in "${compatibility_baselines[@]}" "${conformance_vectors[@]}"; do
  assert_immutable_against_main "$immutable_path"
done

for baseline in "${compatibility_baselines[@]}"; do
  buf breaking --against "$baseline"
done

scripts/check-generated.sh
scripts/check-boundaries.sh

GOWORK=off go test ./...
GOWORK=off go vet ./...

# Prove the independently released wire module first against its committed root
# pin. A workspace-only test can otherwise hide an unreleased or missing root
# dependency and leave the nested module unbuildable after merge.
(
  cd wire-go
  GOWORK=off go test ./...
  GOWORK=off go vet ./...
  GOWORK=off go mod verify
)

# Then compile the wire mapping against the semantic root in this exact
# checkout. Use an ephemeral workspace so no local replace or go.work can leak
# into the published module graph. An intentional root-first release may prove
# that the released mapper fails closed against one exact future shape in its
# mapper tests; the follow-up wire release removes that staging expectation.
workspace_dir="$(mktemp -d)"
trap 'rm -rf "$workspace_dir"' EXIT
(
  cd "$workspace_dir"
  go work init "$repo_root" "$repo_root/wire-go"
)
resolved_semantic_root="$(
  cd wire-go
  GOWORK="$workspace_dir/go.work" go list -m -f '{{.Dir}}' github.com/pingcap-inc/nexuscrm-contract
)"
if [[ "$resolved_semantic_root" != "$repo_root" ]]; then
  echo "wire exact-head gate resolved semantic root to $resolved_semantic_root, want $repo_root" >&2
  exit 1
fi
(
  cd wire-go
  GOWORK="$workspace_dir/go.work" go test ./...
  GOWORK="$workspace_dir/go.work" go vet ./...
)

git diff --check
