package runtimegrpc

import (
	"context"
	"testing"
	"time"

	mailboxauthorizationsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/mailboxauthorizationv1"
	"github.com/pingcap-inc/nexuscrm-contract/wire-go/envelope"
	"google.golang.org/grpc/metadata"
)

func TestPlatformRuntimeConnectedMailboxSeparatesBrowserAndCallbackAuthority(t *testing.T) {
	policy, err := NewPolicyWithIdentityAndOptions(Config{
		Authority: func(context.Context, string) (VerifiedCaller, error) {
			return "sfcrm-workload", nil
		},
		AdmissionLimit: 2,
		AttemptCap:     time.Second,
	}, time.Second, WithPlatformCapabilityMaxAdmissionLease(
		mailboxauthorizationsemantic.CapabilityName,
		time.Second,
	))
	if err != nil {
		t.Fatal(err)
	}
	target, server, transport, cleanup := startPlatformRuntimePolicyTestServer(t, policy)
	defer cleanup()
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel()
	client, err := dialPlatformRuntimeWithCredentials(ctx, RuntimeClientConfig{
		Target: target, AppInstallationID: "installation-1",
		WorkloadToken: "workload-secret", AttemptTimeout: 500 * time.Millisecond,
	}, transport)
	if err != nil {
		t.Fatal(err)
	}
	defer client.Close()

	minimum := uint64(1)
	authorized, err := client.AuthorizeConnectedMailbox(
		ctx,
		"user-secret",
		mailboxauthorizationsemantic.Request{
			Operation:          mailboxauthorizationsemantic.OperationBegin,
			MinCatalogRevision: &minimum,
		},
	)
	if err != nil {
		t.Fatal(err)
	}
	if authorized.AuthorizedSubjectID != "user-1" ||
		authorized.ReauthorizationHandle != "reauthorization-handle-1" ||
		authorized.Receipts.CatalogRevision < minimum {
		t.Fatalf("authorization response = %#v", authorized)
	}

	callbackCtx := metadata.NewOutgoingContext(ctx, metadata.Pairs(
		EndUserAuthorizationMetadataKey, "Bearer stale-browser-secret",
		envelope.RuntimeDelegationMetadataKey, "stale.runtime.delegation",
	))
	reauthorized, err := client.ReauthorizeConnectedMailbox(
		callbackCtx,
		mailboxauthorizationsemantic.ReauthorizeRequest{
			ReauthorizationHandle: authorized.ReauthorizationHandle,
			MinCatalogRevision:    &minimum,
		},
	)
	if err != nil {
		t.Fatal(err)
	}
	if reauthorized.AuthorizedSubjectID != authorized.AuthorizedSubjectID ||
		reauthorized.ReauthorizationHandle != "" ||
		reauthorized.Receipts.CatalogRevision < minimum {
		t.Fatalf("reauthorization response = %#v", reauthorized)
	}
	if server.identityCalls.Load() != 1 || server.mailboxAuthorizeCalls.Load() != 1 ||
		server.mailboxReauthorizeCalls.Load() != 1 {
		t.Fatalf(
			"identity/authorize/reauthorize calls = %d/%d/%d, want 1/1/1",
			server.identityCalls.Load(), server.mailboxAuthorizeCalls.Load(), server.mailboxReauthorizeCalls.Load(),
		)
	}
}
