package runtimeassembly

import (
	"context"
	"errors"
	"testing"

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

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

func (repository *approvalNotificationFlowRepositoryStub) GetAllFlowDefinitions(
	context.Context,
) ([]*models.FlowDefinition, error) {
	return repository.definitions, repository.err
}

func (repository *approvalNotificationFlowRepositoryStub) GetFlowVersion(
	_ context.Context,
	id string,
) (*models.FlowVersion, error) {
	return repository.versions[id], repository.err
}

type approvalNotificationFlowProtectedCatalogStub struct {
	names []string
	err   error
}

func (catalog *approvalNotificationFlowProtectedCatalogStub) ProtectedFlowNames(
	context.Context,
) ([]string, error) {
	return catalog.names, catalog.err
}

func TestApprovalNotificationFlowReadRuntimeUsesStrictRepositoryAndProtectedCatalog(t *testing.T) {
	repository := &approvalNotificationFlowRepositoryStub{
		definitions: []*models.FlowDefinition{
			{Id: "definition-visible", DeveloperName: "Notify_Approver", ActiveVersionId: "version-visible"},
			{Id: "definition-hidden", DeveloperName: "Internal_Notify", ActiveVersionId: "version-hidden"},
		},
		versions: map[string]*models.FlowVersion{
			"version-visible": {DefinitionId: "definition-visible", Status: models.FlowStatusActive},
			"version-hidden":  {DefinitionId: "definition-hidden", Status: models.FlowStatusActive},
		},
	}
	runtime, err := NewApprovalNotificationFlowReadRuntime(
		repository,
		&approvalNotificationFlowProtectedCatalogStub{names: []string{"Internal_Notify"}},
	)
	if err != nil {
		t.Fatal(err)
	}
	definitions, err := runtime.ListApprovalNotificationFlows(t.Context())
	if err != nil {
		t.Fatal(err)
	}
	if len(definitions) != 1 || definitions[0].DeveloperName != "Notify_Approver" {
		t.Fatalf("definitions = %#v", definitions)
	}
}

func TestApprovalNotificationFlowReadRuntimeFailsClosed(t *testing.T) {
	want := errors.New("repository unavailable")
	runtime, err := NewApprovalNotificationFlowReadRuntime(
		&approvalNotificationFlowRepositoryStub{err: want},
		&approvalNotificationFlowProtectedCatalogStub{},
	)
	if err != nil {
		t.Fatal(err)
	}
	if _, err := runtime.ListApprovalNotificationFlows(t.Context()); !errors.Is(err, want) {
		t.Fatalf("error = %v, want %v", err, want)
	}
	if runtime, err := NewApprovalNotificationFlowReadRuntime(nil, &approvalNotificationFlowProtectedCatalogStub{}); err == nil || runtime != nil {
		t.Fatalf("nil repository = %#v, %v", runtime, err)
	}
	if runtime, err := NewApprovalNotificationFlowReadRuntime(&approvalNotificationFlowRepositoryStub{}, nil); err == nil || runtime != nil {
		t.Fatalf("nil protected catalog = %#v, %v", runtime, err)
	}
}
