package graphql

import (
	"context"
	"reflect"
	"testing"
)

func TestConnectionArgsAndCursors(t *testing.T) {
	ctx := context.WithValue(context.Background(), gqlVariablesContextKey{}, map[string]any{
		"first": float64(2), "types": []any{"ISSUE_COMMENT", "ADDED_TO_MERGE_QUEUE_EVENT"},
	})
	query := `query($first: Int!, $types: [PullRequestTimelineItemsItemType!]) {
		repository(owner: "o", name: "r") { pullRequest(number: 1) {
			timelineItems(first: $first, skip: 1, itemTypes: $types) { nodes { __typename } }
		} }
	}`
	args := connectionArgsForField(ctx, query, "", "timelineItems")
	if args.First == nil || *args.First != 2 || args.Skip != 1 ||
		!reflect.DeepEqual(args.ItemTypes, []string{"ISSUE_COMMENT", "ADDED_TO_MERGE_QUEUE_EVENT"}) {
		t.Fatalf("args = %+v", args)
	}

	nodes := []any{"zero", "one", "two", "three"}
	firstPage := gqlConnWithArgs(nodes, gqlConnectionArgs{First: intPointer(2)})
	if got := firstPage["nodes"]; !reflect.DeepEqual(got, []any{"zero", "one"}) {
		t.Fatalf("first page nodes = %#v", got)
	}
	pageInfo := firstPage["pageInfo"].(map[string]any)
	if pageInfo["hasNextPage"] != true || pageInfo["hasPreviousPage"] != false {
		t.Fatalf("first page pageInfo = %#v", pageInfo)
	}
	secondPage := gqlConnWithArgs(nodes, gqlConnectionArgs{After: pageInfo["endCursor"].(string), First: intPointer(2)})
	if got := secondPage["nodes"]; !reflect.DeepEqual(got, []any{"two", "three"}) {
		t.Fatalf("second page nodes = %#v", got)
	}
	secondInfo := secondPage["pageInfo"].(map[string]any)
	if secondInfo["hasNextPage"] != false || secondInfo["hasPreviousPage"] != true {
		t.Fatalf("second page pageInfo = %#v", secondInfo)
	}
}

func TestStackAndMergeQueueEntryArgumentsAreScopedToTheirParent(t *testing.T) {
	query := `{ repository(owner: "o", name: "r") { pullRequest(number: 1) {
		stack { entries(first: 1) { totalCount } }
		mergeQueue { entries(last: 2) { totalCount } }
	} } }`
	stackArgs := connectionArgsForField(context.Background(), query, "stack", "entries")
	queueArgs := connectionArgsForField(context.Background(), query, "mergeQueue", "entries")
	if stackArgs.First == nil || *stackArgs.First != 1 || stackArgs.Last != nil {
		t.Fatalf("stack entries args = %+v", stackArgs)
	}
	if queueArgs.Last == nil || *queueArgs.Last != 2 || queueArgs.First != nil {
		t.Fatalf("merge queue entries args = %+v", queueArgs)
	}
}

func intPointer(value int) *int { return &value }
