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

ROOT="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
GUARDRAIL="$ROOT/guardrails/architecture/check-service-automation-architecture.sh"
FIXTURE="$(mktemp -d "${TMPDIR:-/tmp}/agentteam-service-architecture-guardrail.XXXXXX")"
trap 'rm -rf "$FIXTURE"' EXIT

mkdir -p \
  "$FIXTURE/internal/automation/dsl" \
  "$FIXTURE/internal/core/runeffect" \
  "$FIXTURE/internal/core/webhook" \
  "$FIXTURE/internal/schedule/manage" \
  "$FIXTURE/internal/store/app/webhooks" \
  "$FIXTURE/internal/store/message" \
  "$FIXTURE/internal/store/serviceactor"

cat >"$FIXTURE/internal/store/message/contribution_source.go" <<'GO'
package message

const (
	ContributionSourceKindProviderEvent = "provider_event"
	ContributionSourceKindScheduleRun = "schedule_run"
	ContributionSourceRefTypeServiceEventDelivery = "service_event_delivery"
	ContributionSourceRefTypeAutomationRun = "automation_run"
)

func ContributionSourceForServiceEventDelivery() any {
	return []string{ContributionSourceKindProviderEvent, ContributionSourceRefTypeServiceEventDelivery}
}

func ContributionSourceForAutomationRun() any {
	return []string{ContributionSourceKindScheduleRun, ContributionSourceRefTypeAutomationRun}
}
GO

cat >"$FIXTURE/internal/core/runeffect/contract.go" <<'GO'
package runeffect
type LedgerRefType string
const (
	LedgerRefTypeAutomationRun LedgerRefType = "automation_run"
	LedgerRefTypeServiceEventDelivery LedgerRefType = "service_event_delivery"
)
GO

cat >"$FIXTURE/internal/core/webhook/provider_event.go" <<'GO'
package webhook
func NormalizeGitHubProviderEvent() {}
func NormalizeGiteaProviderEvent() {}
GO

cat >"$FIXTURE/internal/store/serviceactor/store.go" <<'GO'
package serviceactor
GO

cat >"$FIXTURE/internal/automation/dsl/dsl.go" <<'GO'
package dsl
GO

cat >"$FIXTURE/internal/store/app/service_event_delivery.go" <<'GO'
package app
func deliver() {
	NormalizeGitHubProviderEvent()
	NormalizeGiteaProviderEvent()
	ContributionSourceForServiceEventDelivery()
}
GO

cat >"$FIXTURE/internal/store/app/pull_request_subscription_resource_validation.go" <<'GO'
package app
GO

cat >"$FIXTURE/internal/store/app/service_event_subscription_service.go" <<'GO'
package app
func create() {}
GO

cat >"$FIXTURE/internal/store/app/provider_watch_service.go" <<'GO'
package app
func providerFacade() {}
GO

cat >"$FIXTURE/internal/store/app/app_messages.go" <<'GO'
package app
func readMessages() {}
GO

cat >"$FIXTURE/internal/store/app/app_deliveries.go" <<'GO'
package app
GO

cat >"$FIXTURE/internal/store/app/schedule_message_source.go" <<'GO'
package app
import _ "github.com/tidbcloud/AgentTeam/internal/store/schedule"
GO

cat >"$FIXTURE/internal/store/app/service_event_subscription_retention.go" <<'GO'
package app
func retainCanonicalRows() {}
GO

cat >"$FIXTURE/internal/store/app/webhooks/webhooks.go" <<'GO'
package webhooks
GO

cat >"$FIXTURE/internal/schedule/service.go" <<'GO'
package schedule
func deliver() { ContributionSourceForAutomationRun() }
GO

cat >"$FIXTURE/internal/schedule/manage/manage_schedule.go" <<'GO'
package manage
import "github.com/tidbcloud/AgentTeam/internal/store/app"
var _ = app.Store{}
GO

run_guardrail() {
  AGENTTEAM_SERVICE_ARCH_GUARDRAIL_ROOT="$FIXTURE" bash "$GUARDRAIL"
}

run_guardrail >/dev/null

expect_failure() {
  local label="$1" expected="$2"
  shift 2
  local output
  if output="$(run_guardrail 2>&1)"; then
    printf 'FAIL: mutation %s unexpectedly passed\n' "$label" >&2
    exit 1
  fi
  if [[ "$output" != *"$expected"* ]]; then
    printf 'FAIL: mutation %s did not report %q\n%s\n' "$label" "$expected" "$output" >&2
    exit 1
  fi
  "$@"
}

cp "$FIXTURE/internal/store/serviceactor/store.go" "$FIXTURE/serviceactor.store.go"
cat >"$FIXTURE/internal/store/serviceactor/store.go" <<'GO'
package serviceactor
import "github.com/tidbcloud/AgentTeam/internal/store/app"
GO
expect_failure \
  "serviceactor imports app" \
  "lower-level Service Actor/webhook owner must not import" \
  cp "$FIXTURE/serviceactor.store.go" "$FIXTURE/internal/store/serviceactor/store.go"

cp "$FIXTURE/internal/store/app/pull_request_subscription_resource_validation.go" \
  "$FIXTURE/pull_request_subscription_resource_validation.go"
cat >"$FIXTURE/internal/store/app/pull_request_subscription_resource_validation.go" <<'GO'
package app
import _ "github.com/tidbcloud/AgentTeam/internal/automation/dsl"
GO
expect_failure \
  "pull-request subscription imports automation" \
  "App-owned Service Event path must not import" \
  cp "$FIXTURE/pull_request_subscription_resource_validation.go" \
  "$FIXTURE/internal/store/app/pull_request_subscription_resource_validation.go"

cp "$FIXTURE/internal/store/app/service_event_subscription_service.go" \
  "$FIXTURE/service_event_subscription_service.go"
cat >"$FIXTURE/internal/store/app/service_event_subscription_service.go" <<'GO'
package app
import _ "github.com/tidbcloud/AgentTeam/internal/automation/dsl"
GO
expect_failure \
  "service-event subscription imports automation" \
  "App-owned Service Event path must not import" \
  cp "$FIXTURE/service_event_subscription_service.go" \
  "$FIXTURE/internal/store/app/service_event_subscription_service.go"

cp "$FIXTURE/internal/store/app/app_messages.go" "$FIXTURE/app_messages.go"
cat >"$FIXTURE/internal/store/app/app_messages.go" <<'GO'
package app
const retiredTriggerRead = "SELECT id FROM trigger_runs"
GO
expect_failure \
  "App messages reads retired trigger table" \
  "legacy trigger tables are retired" \
  cp "$FIXTURE/app_messages.go" "$FIXTURE/internal/store/app/app_messages.go"

printf '\nconst retiredRead = "SELECT id FROM trigger_definitions"\n' \
  >>"$FIXTURE/internal/store/app/pull_request_subscription_resource_validation.go"
expect_failure \
  "pull-request subscription reads retired trigger table" \
  "legacy trigger tables are retired" \
  cp "$FIXTURE/pull_request_subscription_resource_validation.go" \
  "$FIXTURE/internal/store/app/pull_request_subscription_resource_validation.go"

cp "$FIXTURE/internal/schedule/service.go" "$FIXTURE/schedule.service.go"
printf '\nimported := "github.com/tidbcloud/AgentTeam/internal/store/app"\n' \
  >>"$FIXTURE/internal/schedule/service.go"
expect_failure \
  "native schedule imports app" \
  "native Schedule code must not import App or Service Event" \
  cp "$FIXTURE/schedule.service.go" "$FIXTURE/internal/schedule/service.go"

cp "$FIXTURE/internal/store/message/contribution_source.go" "$FIXTURE/contribution_source.go"
python3 - "$FIXTURE/internal/store/message/contribution_source.go" <<'PY'
import sys
from pathlib import Path
path = Path(sys.argv[1])
path.write_text(path.read_text().replace(
    'ContributionSourceRefTypeServiceEventDelivery = "service_event_delivery"',
    'ContributionSourceRefTypeServiceEventDelivery = "automation_run"',
))
PY
expect_failure \
  "provider source uses automation ledger" \
  "ContributionSourceRefTypeServiceEventDelivery=service_event_delivery" \
  cp "$FIXTURE/contribution_source.go" "$FIXTURE/internal/store/message/contribution_source.go"

cp "$FIXTURE/internal/store/app/service_event_delivery.go" "$FIXTURE/service_event_delivery.go"
sed -i.bak '/NormalizeGiteaProviderEvent/d' "$FIXTURE/internal/store/app/service_event_delivery.go"
rm -f "$FIXTURE/internal/store/app/service_event_delivery.go.bak"
expect_failure \
  "gitea normalizer is bypassed" \
  "Service Event production path must call NormalizeGiteaProviderEvent" \
  cp "$FIXTURE/service_event_delivery.go" "$FIXTURE/internal/store/app/service_event_delivery.go"

run_guardrail >/dev/null
printf 'PASS: service architecture guardrail rejects package-wide ownership, legacy SQL, source, and wiring mutations\n'
