package runtimegrpc

import (
	"context"
	"errors"
	"testing"
	"time"

	defaultsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recorddefaultsv1"
	"github.com/pingcap-inc/nexuscrm-contract/wire-go/envelope"
	runtimev1 "github.com/pingcap-inc/nexuscrm-contract/wire-go/gen/runtime/v1"
	"github.com/pingcap-inc/nexuscrm-contract/wire-go/mapping"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
)

func TestCreateDefaultPreviewClientOwnsTypedCapabilityCall(t *testing.T) {
	var calls int
	minimumCatalogRevision := uint64(41)
	client, err := NewCreateDefaultPreviewClient(func(
		ctx context.Context,
		request *runtimev1.PreviewCreateDefaultsRequest,
		options ...grpc.CallOption,
	) (*runtimev1.PreviewCreateDefaultsResponse, error) {
		calls++
		values, _ := metadata.FromOutgoingContext(ctx)
		assertExactly(t, values.Get(envelope.CapabilityMetadataKey), defaultsemantic.CapabilityName)
		assertClientCallOptions(t, options)
		if request.GetObjectId() != "RankedChild" ||
			request.GetParentFieldId() != "ParentId" ||
			request.GetParentRecordId() != "parent-1" ||
			request.GetMinCatalogRevision() != minimumCatalogRevision {
			t.Fatalf("wire request=%#v", request)
		}
		semanticRequest, err := mapping.FromWirePreviewCreateDefaultsRequest(ctx, request)
		if err != nil {
			t.Fatal(err)
		}
		next := int64(901)
		return mapping.ToWirePreviewCreateDefaultsResponse(semanticRequest, defaultsemantic.Response{
			Fields: []defaultsemantic.Field{{
				Name: "Sequence", Kind: defaultsemantic.ValueInteger,
				Integer: &next, Provenance: defaultsemantic.ProvenanceSiblingMaxPlusOne,
			}},
			Receipts: defaultsemantic.Receipts{
				ProtocolVersion: "1.0", CapabilityVersion: defaultsemantic.CapabilityName,
				CatalogRevision: minimumCatalogRevision,
			},
		})
	})
	if err != nil {
		t.Fatal(err)
	}
	parentField := "ParentId"
	parentRecord := "parent-1"
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	response, err := client.PreviewCreateDefaults(ctx, defaultsemantic.Request{
		ObjectID: "RankedChild", ParentFieldID: &parentField,
		ParentRecordID: &parentRecord, MinCatalogRevision: &minimumCatalogRevision,
	})
	if err != nil || calls != 1 || len(response.Fields) != 1 ||
		response.Fields[0].Integer == nil || *response.Fields[0].Integer != 901 {
		t.Fatalf("response=%#v error=%v calls=%d", response, err, calls)
	}
	if constructed, err := NewCreateDefaultPreviewClient(nil); err == nil || constructed != nil {
		t.Fatalf("NewCreateDefaultPreviewClient(nil)=%#v, %v", constructed, err)
	}
}

func TestCreateDefaultPreviewRequiresExplicitAdmissionLease(t *testing.T) {
	config := Config{
		Authority:      func(context.Context, string) (VerifiedCaller, error) { return "caller", nil },
		AdmissionLimit: 1, AttemptCap: time.Second,
	}
	requestContext := func() (context.Context, context.CancelFunc) {
		return context.WithTimeout(metadata.NewIncomingContext(context.Background(), metadata.Pairs(
			envelope.ProtocolMajorMetadataKey, "1",
			envelope.ProtocolMinorMetadataKey, "0",
			envelope.CapabilityMetadataKey, defaultsemantic.CapabilityName,
		)), 500*time.Millisecond)
	}
	ctx, cancel := requestContext()
	defer cancel()
	disabled := mustPolicy(t, config)
	called := false
	_, err := disabled.UnaryServerInterceptor()(ctx, nil, &grpc.UnaryServerInfo{
		FullMethod: runtimev1.RecordCreateDefaultPreviewService_PreviewCreateDefaults_FullMethodName,
	}, func(context.Context, any) (any, error) {
		called = true
		return nil, nil
	})
	if status.Code(err) != codes.Unimplemented || called {
		t.Fatalf("disabled error=%v called=%v", err, called)
	}

	enabled, err := NewPolicyWithOptions(config, WithCreateDefaultPreviewMaxAdmissionLease(time.Second))
	if err != nil {
		t.Fatal(err)
	}
	ctx2, cancel2 := requestContext()
	defer cancel2()
	_, err = enabled.UnaryServerInterceptor()(ctx2, nil, &grpc.UnaryServerInfo{
		FullMethod: runtimev1.RecordCreateDefaultPreviewService_PreviewCreateDefaults_FullMethodName,
	}, func(handlerCtx context.Context, _ any) (any, error) {
		called = true
		if capability, ok := Capability(handlerCtx); !ok || capability != defaultsemantic.CapabilityName {
			t.Fatalf("capability=%q ok=%v", capability, ok)
		}
		return "ok", nil
	})
	if err != nil || !called {
		t.Fatalf("enabled error=%v called=%v", err, called)
	}

	overLease, cancelOverLease := context.WithTimeout(metadata.NewIncomingContext(context.Background(), metadata.Pairs(
		envelope.ProtocolMajorMetadataKey, "1",
		envelope.ProtocolMinorMetadataKey, "0",
		envelope.CapabilityMetadataKey, defaultsemantic.CapabilityName,
	)), 2*time.Second)
	defer cancelOverLease()
	called = false
	_, err = enabled.UnaryServerInterceptor()(overLease, nil, &grpc.UnaryServerInfo{
		FullMethod: runtimev1.RecordCreateDefaultPreviewService_PreviewCreateDefaults_FullMethodName,
	}, func(context.Context, any) (any, error) {
		called = true
		return nil, nil
	})
	var failure *defaultsemantic.Failure
	if !errors.As(mapping.FromCreateDefaultPreviewStatusError(err), &failure) ||
		failure.Category != defaultsemantic.FailureResourceExhausted ||
		failure.LimitKind != defaultsemantic.LimitAdmission || called {
		t.Fatalf("over-lease error=%#v called=%v", err, called)
	}
}
