package mapping

import (
	"errors"
	"testing"

	common "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commonv1"
	layout "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/layoutauthoringv2"
	search "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/searchv1"
	wire "github.com/pingcap-inc/nexuscrm-contract/wire-go/gen/common/v1"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

func TestConflictReasonBoundary(t *testing.T) {
	for _, reason := range []common.ConflictReason{"", common.ConflictRevisionMismatch, common.ConflictReferenced, common.ConflictDefaultRequired} {
		t.Run(string(reason), func(t *testing.T) {
			encoded := ToPlatformStatusError(&common.Failure{Category: common.FailureConflict, ConflictReason: reason}, layout.CapabilityName)
			decoded := FromPlatformStatusError(encoded, layout.CapabilityName)
			var failure *common.Failure
			if status.Code(encoded) != codes.Aborted || !errors.As(decoded, &failure) || failure.Category != common.FailureConflict || failure.ConflictReason != reason {
				t.Fatalf("conflict round trip: %v, %#v", encoded, decoded)
			}
		})
	}
	for _, test := range []struct {
		name       string
		category   common.FailureCategory
		reason     common.ConflictReason
		capability string
	}{
		{"unknown reason", common.FailureConflict, "secret-internal-cause", layout.CapabilityName},
		{"wrong category", common.FailureMissing, common.ConflictReferenced, layout.CapabilityName},
		{"unsupported capability", common.FailureConflict, common.ConflictReferenced, search.CapabilityName},
	} {
		t.Run(test.name, func(t *testing.T) {
			encoded := ToPlatformStatusError(&common.Failure{Category: test.category, ConflictReason: test.reason}, test.capability)
			if status.Code(encoded) != codes.Internal {
				t.Fatalf("invalid conflict detail accepted: %v", encoded)
			}
		})
	}
	for _, reason := range []wire.ConflictReason{wire.ConflictReason_CONFLICT_REASON_UNSPECIFIED, 999} {
		encoded, err := status.New(codes.Aborted, "untrusted").WithDetails(&wire.RuntimeErrorDetail{
			Category: wire.ErrorCategory_ERROR_CATEGORY_CONFLICT,
			Detail:   &wire.RuntimeErrorDetail_Conflict{Conflict: &wire.ConflictDetail{Reason: reason}},
		})
		if err != nil {
			t.Fatal(err)
		}
		decoded := FromPlatformStatusError(encoded.Err(), layout.CapabilityName)
		var failure *common.Failure
		if !errors.As(decoded, &failure) || failure.Category != common.FailureInternal {
			t.Fatalf("unknown wire reason accepted: %#v", decoded)
		}
	}
}
