package app

import (
	"sort"
	"strings"
)

const (
	ProviderWatchProviderGitHub = PullRequestSubscriptionProviderGitHub
	ProviderWatchProviderGitea  = PullRequestSubscriptionProviderGitea

	ProviderWatchResourcePullRequest = PullRequestSubscriptionResourcePullRequest

	ProviderWatchStatusActive    = ServiceEventSubscriptionStatusActive
	ProviderWatchStatusPaused    = ServiceEventSubscriptionStatusPaused
	ProviderWatchStatusCompleted = ServiceEventSubscriptionStatusCompleted
	ProviderWatchStatusBlocked   = ServiceEventSubscriptionStatusBlocked

	TargetAppBindingStatusActive   = "active"
	TargetAppBindingStatusDisabled = "disabled"

	providerWatchDeliveryPolicy = pullRequestSubscriptionDeliveryPolicy
)

// providerWatchEventKindsForFilters translates the stable provider-watch event
// vocabulary into the canonical provider-event kinds stored by the service
// event subscription ledger.
func providerWatchEventKindsForFilters(provider string, eventFilters []byte) []string {
	prefix := normalizePullRequestSubscriptionProvider(provider) + "_pull_request."
	events := canonicalPullRequestSubscriptionEvents(
		pullRequestSubscriptionFilterEventsFromMap(decodeServiceEventSubscriptionJSONMap(eventFilters)),
	)
	if len(events) == 0 {
		events = defaultPullRequestSubscriptionEventFilters()
	}
	kinds := make([]string, 0, len(events)*2)
	for _, eventName := range events {
		switch eventName {
		case "comments":
			kinds = append(kinds, prefix+"issue_comment_created", prefix+"review_comment_created")
		case "reviews":
			kinds = append(kinds, prefix+"review_submitted")
		case "synchronize":
			kinds = append(kinds, prefix+"synchronized")
		case "base_branch_push":
			kinds = append(kinds, prefix+"base_branch_pushed")
		case "status":
			kinds = append(kinds, prefix+"ci_status", prefix+"workflow_run_status", prefix+"workflow_job_status")
		case "merge", "close":
			kinds = append(kinds, prefix+"closed")
		case "reopen":
			kinds = append(kinds, prefix+"reopened")
		default:
			// Keep the provider event subscription broad for categories not yet
			// represented by a canonical event kind. The delivery path applies
			// the provider-neutral event filter before writing a message.
			return []string{prefix + "*"}
		}
	}
	return sortedUniqueProviderWatchStrings(kinds)
}

func sortedUniqueProviderWatchStrings(values []string) []string {
	if len(values) == 0 {
		return nil
	}
	sort.Strings(values)
	unique := values[:0]
	for _, value := range values {
		if len(unique) == 0 || unique[len(unique)-1] != value {
			unique = append(unique, value)
		}
	}
	return unique
}

func marshalProviderWatchEventFilters(value map[string]any) ([]byte, error) {
	return marshalPullRequestSubscriptionEventFilters(value)
}

// providerAppID is retained for the stable provider authorization facade; the
// canonical subscription helpers own the actual provider-to-service mapping.
func providerAppID(provider string) (string, error) {
	return pullRequestSubscriptionProviderAppID(provider)
}

func normalizeCreatedVia(createdVia string) string {
	return strings.ToLower(strings.TrimSpace(createdVia))
}
