package automation

import (
	"context"
	"errors"
	"testing"

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

type approvalNotificationFlowCatalogTestSource struct {
	definitions []*models.FlowDefinition
	versions    map[string]*models.FlowVersion
	protected   []string
	err         error
}

func (source *approvalNotificationFlowCatalogTestSource) ApprovalNotificationFlowDefinitions(
	context.Context,
) ([]*models.FlowDefinition, error) {
	if source.err != nil {
		return nil, source.err
	}
	return source.definitions, nil
}

func (source *approvalNotificationFlowCatalogTestSource) ApprovalNotificationFlowVersion(
	_ context.Context,
	id string,
) (*models.FlowVersion, error) {
	if source.err != nil {
		return nil, source.err
	}
	return source.versions[id], nil
}

func (source *approvalNotificationFlowCatalogTestSource) ProtectedFlowNames(
	context.Context,
) ([]string, error) {
	if source.err != nil {
		return nil, source.err
	}
	return source.protected, nil
}

func TestListApprovalNotificationFlowDefinitionsOwnsCompleteEligibility(t *testing.T) {
	safe := models.FlowMetadata{ActionCalls: []models.FlowActionCall{{
		Name: "Notify", ActionType: "sendNotification",
	}}}
	unsafe := models.FlowMetadata{RecordUpdates: []models.FlowRecordUpdate{{Name: "Mutate"}}}
	source := &approvalNotificationFlowCatalogTestSource{
		definitions: []*models.FlowDefinition{
			{Id: "definition-z", DeveloperName: "Z_Notify", ActiveVersionId: "version-z"},
			{Id: "definition-protected", DeveloperName: "Std_Internal", ActiveVersionId: "version-protected"},
			{Id: "definition-unsafe", DeveloperName: "Unsafe", ActiveVersionId: "version-unsafe"},
			{Id: "definition-draft", DeveloperName: "Draft", ActiveVersionId: "version-draft"},
			{Id: "definition-a", DeveloperName: "A_Notify", ActiveVersionId: "version-a"},
			{Id: "definition-deleted", DeveloperName: "Deleted", ActiveVersionId: "version-deleted", IsDeleted: true},
		},
		versions: map[string]*models.FlowVersion{
			"version-z":         {Id: "version-z", DefinitionId: "definition-z", Status: models.FlowStatusActive, Metadata: safe},
			"version-protected": {Id: "version-protected", DefinitionId: "definition-protected", Status: models.FlowStatusActive, Metadata: safe},
			"version-unsafe":    {Id: "version-unsafe", DefinitionId: "definition-unsafe", Status: models.FlowStatusActive, Metadata: unsafe},
			"version-draft":     {Id: "version-draft", DefinitionId: "definition-draft", Status: models.FlowStatusDraft, Metadata: safe},
			"version-a":         {Id: "version-a", DefinitionId: "definition-a", Status: models.FlowStatusActive, Metadata: safe},
		},
		protected: []string{" std_internal "},
	}

	definitions, err := ListApprovalNotificationFlowDefinitions(t.Context(), source)
	if err != nil {
		t.Fatal(err)
	}
	if len(definitions) != 2 || definitions[0].DeveloperName != "A_Notify" ||
		definitions[1].DeveloperName != "Z_Notify" {
		t.Fatalf("eligible definitions = %#v", definitions)
	}
}

func TestListApprovalNotificationFlowDefinitionsFailsClosedOnSourceError(t *testing.T) {
	want := errors.New("repository unavailable")
	if _, err := ListApprovalNotificationFlowDefinitions(
		t.Context(),
		&approvalNotificationFlowCatalogTestSource{err: want},
	); !errors.Is(err, want) {
		t.Fatalf("error = %v, want %v", err, want)
	}
	if definitions, err := ListApprovalNotificationFlowDefinitions(t.Context(), nil); err == nil || definitions != nil {
		t.Fatalf("nil source = %#v, %v", definitions, err)
	}
}
