package repo

import (
	"context"

	apiv1 "github.com/tidbcloud/cluster-service-ng/api/cluster-service-ng/v1beta"
	"github.com/tidbcloud/cluster-service-ng/domain/entity"
)

// AutoscalePolicyBundleRow is the per-row storage shape used by the policy
// policy-shaped RPCs. One row per (scope, subject_id). The Specs are
// the canonical AutoscalePolicySpecBundle (which the caller may have
// partially specified — nil field means "follow DEFAULT scope").
type AutoscalePolicyBundleRow struct {
	Scope                 apiv1.AutoscalePolicyScope
	SubjectID             string
	Specs                 []*entity.AutoscalePolicySpec
	ApplyToAllSharedPools *bool // nil = follow DEFAULT scope
	BundleHash            string
}

// AutoscalePolicyBundleFilter narrows a List request. A zero value in any
// field means "no filter on that field". SubjectIDPrefix is a left-anchor
// match (LIKE 'prefix%').
type AutoscalePolicyBundleFilter struct {
	Scope           apiv1.AutoscalePolicyScope
	SubjectIDPrefix string
}

// AutoscalePolicyBundleRepo is the regional persistence for the policy
// policy-shaped RPCs (PR-A). The bundle row is keyed by
// (scope, subject_id) — independent of the existing
// `autoscale_policies` per-SpecKey row that the 3 auto-scaling
// callers consult.
type AutoscalePolicyBundleRepo interface {
	// UpsertBundle writes (or replaces) the row at (scope, subject_id).
	// If the row exists, it is replaced wholesale.
	UpsertBundle(ctx context.Context, row *AutoscalePolicyBundleRow) error

	// GetBundle returns the row at (scope, subject_id), or (nil, nil) if
	// absent. Callers must treat nil-row as "no override at this scope"
	// (i.e., resolve from DEFAULT).
	GetBundle(ctx context.Context, scope apiv1.AutoscalePolicyScope, subjectID string) (*AutoscalePolicyBundleRow, error)

	// DeleteBundle removes the row at (scope, subject_id). Absence is
	// not an error.
	DeleteBundle(ctx context.Context, scope apiv1.AutoscalePolicyScope, subjectID string) error

	// ListBundles returns rows matching the filter, paged by pageSize.
	// pageToken is opaque; pass "" for the first page. The next page
	// token (when non-empty) is returned in NextPageToken.
	ListBundles(ctx context.Context, filter AutoscalePolicyBundleFilter, pageSize uint32, pageToken string) ([]*AutoscalePolicyBundleRow, string, error)
}
