package registry

import (
	"fmt"
)

// ValidateAppScopeSubset validates a narrowed scope subset against a pinned App
// capability. It enforces only the scope-driven co-constraints that mirror the
// manifest rules in developer_manifest.go: a retained scope must keep its
// declared dependencies. It does NOT re-check R ⊆ S (callers enforce that
// separately) and does not mutate the capability.
func ValidateAppScopeSubset(capability StoredAppRuntimeCapability, scopes []string) error {
	normalized := SortedUniqueScopes(scopes)
	hasScope := func(name string) bool { return containsString(normalized, name) }

	hasMentionEvent := containsString(capability.Events, AppEventMessageMention)
	hasActionEvent := containsString(capability.Events, AppEventNotificationAction)

	if hasScope("app.mentions.read") {
		if !hasMentionEvent {
			return badRequest("scope app.mentions.read requires the agentteam.message.mention event")
		}
		if !hasScope("messages.write") {
			return badRequest("scope app.mentions.read requires messages.write")
		}
	}
	if hasScope("app.notifications.write") {
		if !capability.Notifications.Supported {
			return badRequest("scope app.notifications.write requires the notifications capability")
		}
		if !hasScope("messages.write") {
			return badRequest("scope app.notifications.write requires messages.write")
		}
	}
	if hasScope("app.notification_actions.read") {
		if !hasActionEvent {
			return badRequest("scope app.notification_actions.read requires the agentteam.app.notification.action event")
		}
		if !capability.Notifications.Supported || !containsString(capability.Notifications.Content, AppNotificationContentInteractiveCard) {
			return badRequest(fmt.Sprintf("scope app.notification_actions.read requires the %s notification content", AppNotificationContentInteractiveCard))
		}
	}
	return nil
}
