package app

import (
	"fmt"
	"sort"
	"strings"

	"github.com/tidbcloud/AgentTeam/internal/core/webhook"
	"github.com/tidbcloud/AgentTeam/internal/store/model"
	"github.com/tidbcloud/AgentTeam/internal/store/provider"
)

func buildServiceEventSourceOccurrenceRef(event serviceEventProviderWebhookEvent) string {
	return strings.TrimSpace(event.Installation.WorkspaceID) + ":" + strings.TrimSpace(event.Event.EventID)
}

func providerEventActionSnapshot(event provider.ProviderEvent) string {
	return firstNonEmpty(strings.TrimSpace(event.ActionKind), strings.TrimSpace(event.EventKind))
}

func serviceEventDeliveryPayload(event serviceEventProviderWebhookEvent) ([]byte, error) {
	payload, err := model.MarshalJSONObject("service event provider payload", model.ProviderEventPayload{
		Provider:           strings.TrimSpace(event.Event.Provider),
		ResourceIdentifier: strings.TrimSpace(event.Event.ResourceIdentifier),
		ResourceURL:        strings.TrimSpace(event.Event.ResourceURL),
		EventID:            strings.TrimSpace(event.Event.EventID),
		DeliveryKey:        strings.TrimSpace(event.DeliveryKey),
		EventType:          strings.TrimSpace(event.EventType),
		EventKind:          strings.TrimSpace(event.Event.EventKind),
		ActionKind:         strings.TrimSpace(event.Event.ActionKind),
		ActorLogin:         strings.TrimSpace(event.Event.ActorLogin),
		BodyExcerpt:        webhook.TruncateProviderText(strings.TrimSpace(event.Event.BodyExcerpt), serviceEventBodyExcerptMaxBytes),
		ChangedPaths:       serviceEventProviderChangedPaths(event.Event.ChangedPaths),
		Extra:              serviceEventProviderStoredExtra(event.Event.Extra),
	})
	if err != nil {
		return nil, fmt.Errorf("encode service event provider payload: %w", err)
	}
	return payload, nil
}

func nullIfBlankString(value string) any {
	trimmed := strings.TrimSpace(value)
	if trimmed == "" {
		return nil
	}
	return trimmed
}

func providerEventFromCore(event webhook.ProviderEvent) provider.ProviderEvent {
	return provider.ProviderEvent{
		Provider:           event.Provider,
		WorkspaceID:        event.WorkspaceID,
		EventKind:          event.EventKind,
		EventID:            event.EventID,
		OccurredAt:         event.OccurredAt,
		ConnectionRef:      event.ConnectionRef,
		ResourceIdentifier: event.ResourceIdentifier,
		ResourceURL:        event.ResourceURL,
		ActorLogin:         event.ActorLogin,
		ActionKind:         event.ActionKind,
		BodyExcerpt:        event.BodyExcerpt,
		ChangedPaths:       event.ChangedPaths,
		Extra:              event.Extra,
	}
}

func serviceEventProviderChangedPaths(values []string) []string {
	if len(values) == 0 {
		return nil
	}
	seen := make(map[string]struct{}, len(values))
	out := make([]string, 0, len(values))
	totalBytes := 0
	for _, value := range values {
		path := strings.TrimSpace(value)
		if path == "" {
			continue
		}
		if _, ok := seen[path]; ok {
			continue
		}
		totalBytes += len(path)
		if totalBytes > serviceEventBodyExcerptMaxBytes {
			return nil
		}
		seen[path] = struct{}{}
		out = append(out, path)
	}
	if len(out) == 0 {
		return nil
	}
	sort.Strings(out)
	return out
}
