package admin

import (
	"context"
	"errors"
	"testing"

	"github.com/wangjia/pangolin/server/internal/provision"
)

// fakeReplacer records the arguments passed to Replace and returns canned values.
type fakeReplacer struct {
	gotNodeID int64
	gotUUID   string
	res       *provision.ReplaceResult
	err       error
}

func (f *fakeReplacer) Replace(_ context.Context, nodeID int64, uuid string) (*provision.ReplaceResult, error) {
	f.gotNodeID, f.gotUUID = nodeID, uuid
	return f.res, f.err
}

func TestRealProvision_Replace_DelegatesWithFreshUUID(t *testing.T) {
	f := &fakeReplacer{res: &provision.ReplaceResult{NewNodeID: 99}}
	p := NewRealProvision(f)

	if err := p.Replace(context.Background(), 42, "operator"); err != nil {
		t.Fatalf("Replace: %v", err)
	}
	if f.gotNodeID != 42 {
		t.Errorf("nodeID = %d, want 42", f.gotNodeID)
	}
	// Admin always starts a fresh orchestration: the service mints its own key.
	if f.gotUUID != "" {
		t.Errorf("replacementUUID = %q, want empty (fresh start)", f.gotUUID)
	}
	if !p.Ready() {
		t.Error("RealProvision.Ready() = false, want true")
	}
}

func TestRealProvision_Replace_PropagatesError(t *testing.T) {
	sentinel := errors.New("no vendor credentials")
	p := NewRealProvision(&fakeReplacer{err: sentinel})
	if err := p.Replace(context.Background(), 7, "operator"); !errors.Is(err, sentinel) {
		t.Errorf("Replace error = %v, want %v", err, sentinel)
	}
}

func TestRealLifecycle_RejectsUnsupportedTarget(t *testing.T) {
	// Target validation happens before any DB access, so a nil db is safe here.
	l := &RealLifecycle{}
	if err := l.TransitionStatus(context.Background(), 1, "destroyed", "operator"); err == nil {
		t.Error("TransitionStatus with target=destroyed should error, got nil")
	}
	if !l.Ready() {
		t.Error("RealLifecycle.Ready() = false, want true")
	}
}
