package k8sresource

import (
	"fmt"

	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"
)

const (
	defaultSummaryLimit = 200
	maxSummaryLimit     = 1000
	defaultDetailLimit  = 20
	maxDetailLimit      = 100

	listModeSummary = "summary"
	listModeDetail  = "detail"
)

func listLimitConfig(detail bool) (defaultLimit, maxLimit int, mode string) {
	if detail {
		return defaultDetailLimit, maxDetailLimit, listModeDetail
	}
	return defaultSummaryLimit, maxSummaryLimit, listModeSummary
}

func resolveListLimit(opt *regionalpb.Option, detail bool) (int64, error) {
	defaultLimit, maxLimit, mode := listLimitConfig(detail)
	requested := int32(0)
	if opt != nil {
		requested = opt.MaxItems
	}
	if requested <= 0 {
		return int64(defaultLimit), nil
	}
	if requested > int32(maxLimit) {
		return 0, bizerr.New(bizerr.ParameterInvalid,
			fmt.Sprintf("option.max_items=%d exceeds max %d for %s mode", requested, maxLimit, mode))
	}
	return int64(requested), nil
}

func resolveTruncatedWithHintsFromList(list metav1.ListInterface, appliedLimit int64, detail bool, withFieldFilter bool) (truncated bool, hints string) {
	if list == nil {
		return false, ""
	}
	return resolveTruncatedWithHintsFromListMeta(metav1.ListMeta{
		Continue:           list.GetContinue(),
		RemainingItemCount: list.GetRemainingItemCount(),
	}, appliedLimit, detail, withFieldFilter)
}

func resolveTruncatedWithHintsFromListMeta(meta metav1.ListMeta, appliedLimit int64, detail bool, withFieldFilter bool) (truncated bool, hints string) {
	if meta.RemainingItemCount != nil && *meta.RemainingItemCount > 0 {
		truncated = true
	}
	if meta.Continue != "" {
		truncated = true
	}
	if !truncated {
		return false, ""
	}

	_, maxLimit, mode := listLimitConfig(detail)

	beforeFieldFilter := ""
	if withFieldFilter {
		beforeFieldFilter = " (before field filter)"
	}

	if meta.RemainingItemCount != nil && *meta.RemainingItemCount > 0 {
		return true, fmt.Sprintf(
			"listed items capped at limit %d; at least %d more may exist%s; narrow selector or increase option.max_items (max %d for %s)",
			appliedLimit, *meta.RemainingItemCount, beforeFieldFilter, maxLimit, mode,
		)
	}
	return true, fmt.Sprintf(
		"listed items capped at limit %d; more items may exist%s; narrow selector or increase option.max_items (max %d for %s)",
		appliedLimit, beforeFieldFilter, maxLimit, mode,
	)
}
