package automation

import (
	"context"
	"fmt"
	"sort"
	"strings"

	"github.com/nexuscrm/shared/pkg/models"
)

// ApprovalNotificationFlowCatalogSource is the one neutral read path for
// determining which stored Flows may be selected by an approval notification.
// Implementations may be repository-backed, but must surface read failures
// instead of turning them into an empty catalog.
type ApprovalNotificationFlowCatalogSource interface {
	ApprovalNotificationFlowDefinitions(context.Context) ([]*models.FlowDefinition, error)
	ApprovalNotificationFlowVersion(context.Context, string) (*models.FlowVersion, error)
	ProtectedFlowNames(context.Context) ([]string, error)
}

// ListApprovalNotificationFlowDefinitions returns active, non-protected Flows
// whose active version satisfies the narrow notification-only execution
// profile. The result is canonical and contains descriptors only; callers do
// not acquire Flow execution authority through this read.
func ListApprovalNotificationFlowDefinitions(
	ctx context.Context,
	source ApprovalNotificationFlowCatalogSource,
) ([]*models.FlowDefinition, error) {
	if source == nil {
		return nil, fmt.Errorf("approval notification Flow catalog source is not configured")
	}
	protectedNames, err := source.ProtectedFlowNames(ctx)
	if err != nil {
		return nil, fmt.Errorf("read protected Flow catalog: %w", err)
	}
	protected := make(map[string]struct{}, len(protectedNames))
	for _, name := range protectedNames {
		if key := approvalNotificationFlowKey(name); key != "" {
			protected[key] = struct{}{}
		}
	}
	definitions, err := source.ApprovalNotificationFlowDefinitions(ctx)
	if err != nil {
		return nil, fmt.Errorf("read Flow definitions: %w", err)
	}
	result := make([]*models.FlowDefinition, 0, len(definitions))
	for _, definition := range definitions {
		if definition == nil || definition.IsDeleted ||
			strings.TrimSpace(definition.DeveloperName) == "" ||
			strings.TrimSpace(definition.ActiveVersionId) == "" {
			continue
		}
		if _, hidden := protected[approvalNotificationFlowKey(definition.DeveloperName)]; hidden {
			continue
		}
		version, readErr := source.ApprovalNotificationFlowVersion(ctx, definition.ActiveVersionId)
		if readErr != nil {
			return nil, fmt.Errorf("read active Flow version %q: %w", definition.ActiveVersionId, readErr)
		}
		if version == nil || version.IsDeleted ||
			!strings.EqualFold(strings.TrimSpace(version.Status), models.FlowStatusActive) ||
			!strings.EqualFold(strings.TrimSpace(version.DefinitionId), strings.TrimSpace(definition.Id)) {
			continue
		}
		if validateErr := ValidateApprovalNotificationFlowMetadata(
			definition.DeveloperName,
			&version.Metadata,
		); validateErr != nil {
			continue
		}
		result = append(result, definition)
	}
	sort.Slice(result, func(left, right int) bool {
		leftKey := approvalNotificationFlowKey(result[left].DeveloperName)
		rightKey := approvalNotificationFlowKey(result[right].DeveloperName)
		if leftKey != rightKey {
			return leftKey < rightKey
		}
		return result[left].DeveloperName < result[right].DeveloperName
	})
	return result, nil
}

func approvalNotificationFlowKey(value string) string {
	return strings.ToLower(strings.TrimSpace(value))
}
