package runtimework

import (
	"context"
	"strings"
	"testing"

	"github.com/nexuscrm/persistence"
)

func activationConfigJSON(epoch string) string {
	return `{"schema":"` + ConfigSchemaV1 + `","operationId":"d2b-test2-activate-1","workFamily":"runtime.record-events.v1","deploymentId":"runtime-worker-test2-1","workerReleaseDigest":"sha256:` + strings.Repeat("a", 64) + `","expectedOwnershipEpoch":"` + epoch + `"}`
}

func TestParseConfigIsStrictAndPreservesExactEpoch(t *testing.T) {
	config, err := ParseConfig([]byte(activationConfigJSON("18446744073709551614")))
	if err != nil {
		t.Fatal(err)
	}
	request, err := config.Activation()
	if err != nil {
		t.Fatal(err)
	}
	if request.ExpectedOwnershipEpoch != ^uint64(0)-1 {
		t.Fatalf("expected epoch = %d", request.ExpectedOwnershipEpoch)
	}

	for _, raw := range []string{
		strings.Replace(activationConfigJSON("0"), `"operationId":`, `"operationId":"duplicate","operationId":`, 1),
		strings.Replace(activationConfigJSON("0"), `"workFamily":`, `"unknown":true,"workFamily":`, 1),
		activationConfigJSON("01"),
		activationConfigJSON("18446744073709551615"),
		strings.Replace(activationConfigJSON("0"), "runtime.record-events.v1", "bad/family", 1),
	} {
		if _, err := ParseConfig([]byte(raw)); err == nil {
			t.Fatalf("invalid config was accepted: %s", raw)
		}
	}
}

func TestApplyBindsAndVerifiesTheExactActivation(t *testing.T) {
	config, err := ParseConfig([]byte(activationConfigJSON("7")))
	if err != nil {
		t.Fatal(err)
	}
	output, err := Apply(context.Background(), func(_ context.Context, request persistence.RuntimeWorkOwnershipActivation) (persistence.RuntimeWorkOwnership, error) {
		return persistence.RuntimeWorkOwnership{
			WorkFamily: request.WorkFamily, DeploymentID: request.DeploymentID,
			WorkerReleaseDigest: request.WorkerReleaseDigest, OwnershipEpoch: 8,
		}, nil
	}, config)
	if err != nil {
		t.Fatal(err)
	}
	if output.OwnershipEpoch != "8" || output.OperationID != "d2b-test2-activate-1" {
		t.Fatalf("activation output = %#v", output)
	}
}

func TestMarshalOutputIsCanonicalAndContentAddressed(t *testing.T) {
	config, err := ParseConfig([]byte(activationConfigJSON("0")))
	if err != nil {
		t.Fatal(err)
	}
	output, err := Apply(context.Background(), func(_ context.Context, request persistence.RuntimeWorkOwnershipActivation) (persistence.RuntimeWorkOwnership, error) {
		return persistence.RuntimeWorkOwnership{
			WorkFamily: request.WorkFamily, DeploymentID: request.DeploymentID,
			WorkerReleaseDigest: request.WorkerReleaseDigest, OwnershipEpoch: 1,
		}, nil
	}, config)
	if err != nil {
		t.Fatal(err)
	}
	first, firstDigest, err := MarshalOutput(output)
	if err != nil {
		t.Fatal(err)
	}
	second, secondDigest, err := MarshalOutput(output)
	if err != nil {
		t.Fatal(err)
	}
	if string(first) != string(second) || firstDigest != secondDigest || !strings.HasPrefix(firstDigest, "sha256:") {
		t.Fatalf("canonical output mismatch: %s %s / %s %s", first, firstDigest, second, secondDigest)
	}
}
