package k8sresource

import (
	"strings"
	"testing"

	regionalpb "github.com/tidbcloud/infra-provider/api/tidbcloud/regional-server/v1"
	bizerr "github.com/tidbcloud/infra-provider/regional-server/pkg/common/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestResolveListLimit(t *testing.T) {
	tests := []struct {
		name    string
		opt     *regionalpb.Option
		detail  bool
		want    int64
		wantErr bool
	}{
		{
			name:   "summary default",
			detail: false,
			want:   defaultSummaryLimit,
		},
		{
			name:   "detail default",
			detail: true,
			want:   defaultDetailLimit,
		},
		{
			name:   "summary explicit",
			opt:    &regionalpb.Option{MaxItems: 50},
			detail: false,
			want:   50,
		},
		{
			name:    "summary exceeds max",
			opt:     &regionalpb.Option{MaxItems: 1001},
			detail:  false,
			wantErr: true,
		},
		{
			name:    "detail exceeds max",
			opt:     &regionalpb.Option{Detail: true, MaxItems: 101},
			detail:  true,
			wantErr: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got, err := resolveListLimit(tt.opt, tt.detail)
			if (err != nil) != tt.wantErr {
				t.Fatalf("resolveListLimit() error = %v, wantErr %v", err, tt.wantErr)
			}
			if err != nil {
				if _, ok := err.(bizerr.Error); !ok {
					t.Fatalf("expected bizerr.Error, got %T", err)
				}
				return
			}
			if got != tt.want {
				t.Fatalf("resolveListLimit() = %d, want %d", got, tt.want)
			}
		})
	}
}

func TestResolveTruncatedWithHintsFromListMeta(t *testing.T) {
	remaining := int64(5)
	tests := []struct {
		name            string
		meta            metav1.ListMeta
		appliedLimit    int64
		detail          bool
		withFieldFilter bool
		wantTruncated   bool
		wantSubstrings  []string
	}{
		{
			name:          "no truncation",
			meta:          metav1.ListMeta{},
			appliedLimit:  200,
			wantTruncated: false,
		},
		{
			name: "continue token",
			meta: metav1.ListMeta{
				Continue: "next-page",
			},
			appliedLimit:   200,
			wantTruncated:  true,
			wantSubstrings: []string{"capped at limit 200", "summary"},
		},
		{
			name: "remaining item count",
			meta: metav1.ListMeta{
				RemainingItemCount: &remaining,
			},
			appliedLimit:    20,
			detail:          true,
			withFieldFilter: true,
			wantTruncated:   true,
			wantSubstrings:  []string{"at least 5 more", "before field filter", "detail"},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			truncated, hints := resolveTruncatedWithHintsFromListMeta(
				tt.meta, tt.appliedLimit, tt.detail, tt.withFieldFilter,
			)
			if truncated != tt.wantTruncated {
				t.Fatalf("truncated = %v, want %v", truncated, tt.wantTruncated)
			}
			for _, sub := range tt.wantSubstrings {
				if !strings.Contains(hints, sub) {
					t.Fatalf("hints = %q, want substring %q", hints, sub)
				}
			}
		})
	}
}
