package controlplane

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

	"github.com/nexuscrm/metadata"
)

// ReadActiveRuntimeSearchScopeOrder reads the installed declarations through
// immutable pack-generation authority. It preserves pack-name order followed
// by authored item order; it never consults a process-local registry or an
// AppRelease's original defaults. The caller supplies the Catalog transaction.
func ReadActiveRuntimeSearchScopeOrder(ctx context.Context, tx PackGenerationAuthorityExecutor) ([]metadata.SearchScopeOrderItem, error) {
	if ctx == nil || tx == nil {
		return nil, fmt.Errorf("%w: context and generation authority transaction are required", ErrPackGenerationPrecondition)
	}
	generations, err := readActivePackGenerationsForCatalog(ctx, tx)
	if err != nil {
		return nil, err
	}
	return searchScopeOrderFromGenerations(generations)
}

func searchScopeOrderFromGenerations(generations []sourceBackedPackGeneration) ([]metadata.SearchScopeOrderItem, error) {
	result := make([]metadata.SearchScopeOrderItem, 0)
	for _, generation := range generations {
		var items []metadata.SearchScopeOrderItem
		if err := json.Unmarshal([]byte(generation.runtimeSearchScope.String), &items); err != nil {
			return nil, fmt.Errorf("decode active pack %q search-scope declarations: %w", generation.packName, err)
		}
		result = append(result, items...)
	}
	// The existing declaration validator rejects duplicate object ownership,
	// including case-only conflicts across active packs.
	if err := metadata.ValidatePackSearchScopeOrder(result); err != nil {
		return nil, fmt.Errorf("validate active search-scope declarations: %w", err)
	}
	return result, nil
}
