package execution

import (
	"context"
	"errors"
	"reflect"
	"strings"
	"testing"
)

type registryProvider struct {
	name       string
	startErr   error
	lifecycle  *[]string
	startedKey string
	stoppedKey string
}

func (p *registryProvider) Name() string { return p.name }

func (p *registryProvider) Capabilities(context.Context) (Capabilities, error) {
	return Capabilities{AdapterName: p.name}, nil
}

func (p *registryProvider) Execute(context.Context, ExecutionSpec, EventSink) error {
	return nil
}

func (p *registryProvider) Start(context.Context) error {
	*p.lifecycle = append(*p.lifecycle, p.startedKey)
	return p.startErr
}

func (p *registryProvider) Stop(context.Context) error {
	*p.lifecycle = append(*p.lifecycle, p.stoppedKey)
	return nil
}

func TestRegistryLookupAndLifecycleRollback(t *testing.T) {
	var lifecycle []string
	registry := NewRegistry()
	registry.RegisterKeyed("cli-a", "cli", &registryProvider{
		name:       "cli",
		lifecycle:  &lifecycle,
		startedKey: "start-a",
		stoppedKey: "stop-a",
	})
	registry.RegisterKeyed("cli-b", "cli", &registryProvider{
		name:       "cli",
		startErr:   errors.New("failed"),
		lifecycle:  &lifecycle,
		startedKey: "start-b",
		stoppedKey: "stop-b",
	})

	if _, err := registry.Lookup("cli"); err == nil || !strings.Contains(err.Error(), "ambiguous") {
		t.Fatalf("Lookup(cli) error = %v", err)
	}
	if provider, err := registry.Lookup("cli-a"); err != nil || provider.Name() != "cli" {
		t.Fatalf("Lookup(cli-a) = %v, %v", provider, err)
	}
	if err := registry.Start(context.Background()); err == nil {
		t.Fatal("Start() error = nil")
	}
	if want := []string{"start-a", "start-b", "stop-a"}; !reflect.DeepEqual(lifecycle, want) {
		t.Fatalf("lifecycle = %#v, want %#v", lifecycle, want)
	}
}
