package mapping

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

	commonsemantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/commonv1"
	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/mailboxauthorizationv1"
)

func TestMailboxAuthorizationWireRoundTrip(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	minimum := uint64(41)
	request := semantic.Request{Operation: semantic.OperationBegin, MinCatalogRevision: &minimum}
	wireRequest, err := ToWireAuthorizeConnectedMailboxRequest(ctx, request)
	if err != nil {
		t.Fatal(err)
	}
	decodedRequest, err := FromWireAuthorizeConnectedMailboxRequest(ctx, wireRequest)
	if err != nil || !reflect.DeepEqual(decodedRequest, request) {
		t.Fatalf("request round trip = %#v, %v", decodedRequest, err)
	}

	response := semantic.Response{AuthorizedSubjectID: "user-1", ReauthorizationHandle: "reauth-opaque-1", Receipts: semantic.Receipts{
		ProtocolVersion: "1.0", CapabilityVersion: semantic.CapabilityName,
		CatalogRevision: 41, SchemaGeneration: 7, EngineGeneration: 9, SecurityEpoch: 13,
	}}
	wireResponse, err := ToWireAuthorizeConnectedMailboxResponse(request, response)
	if err != nil {
		t.Fatal(err)
	}
	decodedResponse, err := FromWireAuthorizeConnectedMailboxResponse(request, wireResponse)
	if err != nil || !reflect.DeepEqual(decodedResponse, response) {
		t.Fatalf("response round trip = %#v, %v", decodedResponse, err)
	}
}

func TestMailboxAuthorizationStatusPreservesOnlyReviewedFailures(t *testing.T) {
	for _, failure := range []*commonsemantic.Failure{
		{Category: commonsemantic.FailureInvalidRequest, InvalidComponent: commonsemantic.InvalidComponentCommandData},
		{Category: commonsemantic.FailureInvalidRequest, InvalidComponent: commonsemantic.InvalidComponentDeadline},
		{Category: commonsemantic.FailureResourceExhausted, LimitKind: commonsemantic.LimitSemanticRequest, Maximum: semantic.MaxSemanticRequestBytes},
		{Category: commonsemantic.FailureForbidden},
	} {
		decoded := FromPlatformStatusError(ToPlatformStatusError(failure, semantic.CapabilityName), semantic.CapabilityName)
		var roundTrip *commonsemantic.Failure
		if !errors.As(decoded, &roundTrip) || !reflect.DeepEqual(roundTrip, failure) {
			t.Fatalf("failure round trip = %#v, want %#v", decoded, failure)
		}
	}
	foreign := &commonsemantic.Failure{Category: commonsemantic.FailureInvalidRequest, InvalidComponent: commonsemantic.InvalidComponentObjectID}
	decoded := FromPlatformStatusError(ToPlatformStatusError(foreign, semantic.CapabilityName), semantic.CapabilityName)
	var sanitized *commonsemantic.Failure
	if !errors.As(decoded, &sanitized) || sanitized.Category != commonsemantic.FailureInternal {
		t.Fatalf("foreign failure = %#v, want INTERNAL", decoded)
	}
}

func TestMailboxCallbackReauthorizationWireRoundTrip(t *testing.T) {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	request := semantic.ReauthorizeRequest{ReauthorizationHandle: "reauth-opaque-1"}
	wireRequest, err := ToWireReauthorizeConnectedMailboxRequest(ctx, request)
	if err != nil {
		t.Fatal(err)
	}
	decodedRequest, err := FromWireReauthorizeConnectedMailboxRequest(ctx, wireRequest)
	if err != nil || !reflect.DeepEqual(decodedRequest, request) {
		t.Fatalf("request round trip = %#v, %v", decodedRequest, err)
	}
	response := semantic.Response{AuthorizedSubjectID: "user-1", Receipts: semantic.Receipts{
		ProtocolVersion: "1.0", CapabilityVersion: semantic.CapabilityName,
		CatalogRevision: 41, SchemaGeneration: 7, EngineGeneration: 9, SecurityEpoch: 13,
	}}
	wireResponse, err := ToWireReauthorizeConnectedMailboxResponse(request, response)
	if err != nil {
		t.Fatal(err)
	}
	decodedResponse, err := FromWireReauthorizeConnectedMailboxResponse(request, wireResponse)
	if err != nil || !reflect.DeepEqual(decodedResponse, response) {
		t.Fatalf("response round trip = %#v, %v", decodedResponse, err)
	}
}
