package issuetrackerconformance

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

	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/queryv1"
)

func TestIssueQueryConsumerUsesIndependentTypedNeutralShape(t *testing.T) {
	want := IssueRetryFloorRequest(0)
	if want.Filter.Value == nil || want.Filter.Value.Unsigned == nil || *want.Filter.Value.Unsigned != 0 || want.Filter.Value.Decimal != nil {
		t.Fatalf("fixture predicate = %#v, want typed unsigned zero", want.Filter.Value)
	}
	subject := "App-neutral query"
	id := "ISS-Q-1"
	retry := uint64(0)
	response := semantic.Response{
		TotalSize: 1,
		Done:      true,
		Records: []semantic.Record{{
			ObjectID: IssueObject,
			Fields: []semantic.Field{
				{Name: "Id", Value: semantic.Value{Kind: semantic.ValueReference, Reference: &id}},
				{Name: "RetryCount", Value: semantic.Value{Kind: semantic.ValueUnsigned, Unsigned: &retry}},
				{Name: "Subject", Value: semantic.Value{Kind: semantic.ValueString, String: &subject}},
			},
		}},
		Receipts: semantic.Receipts{
			ProtocolVersion: "1.0", CapabilityVersion: semantic.CapabilityName,
			CatalogRevision: 1, SchemaGeneration: 1, EngineGeneration: 1, SecurityEpoch: 1,
		},
	}
	calls := 0
	consumer, err := NewIssueQueryConsumer(func(_ context.Context, request semantic.Request) (semantic.Response, error) {
		calls++
		if !reflect.DeepEqual(request, want) {
			t.Fatalf("query request = %#v, want %#v", request, want)
		}
		return response, nil
	})
	if err != nil {
		t.Fatal(err)
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	got, err := consumer.ListByRetryFloor(ctx, 0)
	if err != nil {
		t.Fatal(err)
	}
	if calls != 1 || !reflect.DeepEqual(got, response) {
		t.Fatalf("query calls=%d response=%#v", calls, got)
	}
}

func TestIssueQueryConsumerFailsBeforeCallingTheNextOwner(t *testing.T) {
	if _, err := NewIssueQueryConsumer(nil); err == nil {
		t.Fatal("nil query operation was accepted")
	}
	calls := 0
	consumer, err := NewIssueQueryConsumer(func(context.Context, semantic.Request) (semantic.Response, error) {
		calls++
		return semantic.Response{}, errors.New("must not be reached")
	})
	if err != nil {
		t.Fatal(err)
	}
	ctx, cancel := context.WithCancel(context.Background())
	cancel()
	if _, err := consumer.ListByRetryFloor(ctx, 0); err == nil {
		t.Fatal("canceled query succeeded")
	}
	if calls != 0 {
		t.Fatalf("canceled query reached the next owner %d times", calls)
	}
}
