package catalogreconcile

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"

	"github.com/nexuscrm/metadata"
	consumerv1 "github.com/pingcap-inc/nexuscrm-contract/pkg/catalog/consumerv1"
	controlplane "github.com/pingcap-inc/nexuscrm-controlplane"
	"github.com/pingcap-inc/nexuscrm-controlplane/catalogapp"
	"github.com/pingcap-inc/nexuscrm-controlplane/componentbehavior"
)

type EffectiveSearchScopeMetadataReader interface {
	GetRuntimeSearchScopeOrder(context.Context) ([]metadata.SearchScopeOrderItem, error)
}

func buildEffectiveSearchScopeComponent(ctx context.Context, reader EffectiveSearchScopeMetadataReader, objectNames []string) (catalogapp.EffectiveMetadataComponent, error) {
	items, err := reader.GetRuntimeSearchScopeOrder(ctx)
	if err != nil {
		return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf("read effective search scope: %w", err)
	}
	if err := metadata.ValidatePackSearchScopeOrder(items); err != nil {
		return catalogapp.EffectiveMetadataComponent{}, fmt.Errorf("validate effective search scope: %w", err)
	}
	objects := make(map[string]bool, len(objectNames))
	for _, name := range objectNames {
		objects[strings.ToLower(name)] = true
	}
	selected := make([]metadata.SearchScopeOrderItem, 0, len(items))
	for _, item := range items {
		if objects[strings.ToLower(item.Name)] {
			selected = append(selected, item)
		}
	}
	raw, err := json.Marshal(selected)
	if err != nil {
		return catalogapp.EffectiveMetadataComponent{}, err
	}
	behavior, err := componentbehavior.CanonicalJSONV1(raw)
	if err != nil {
		return catalogapp.EffectiveMetadataComponent{}, err
	}
	return catalogapp.EffectiveMetadataComponent{
		ComponentKind:          consumerv1.EffectiveSearchScopeComponentKind,
		ComponentFormatVersion: 1,
		BusinessKey:            consumerv1.EffectiveSearchScopeComponentBusinessKey,
		CanonicalBehavior:      behavior,
		ContentDigest:          consumerv1.ComputeEffectiveMetadataComponentDigest(behavior),
	}, nil
}

func (r *RepositoryMetadataReader) GetRuntimeSearchScopeOrder(ctx context.Context) ([]metadata.SearchScopeOrderItem, error) {
	return controlplane.ReadActiveRuntimeSearchScopeOrder(ctx, r.GetExecutor(ctx))
}

var _ EffectiveSearchScopeMetadataReader = (*RepositoryMetadataReader)(nil)
