package dialectsfcrm

import (
	"context"
	"fmt"
	"sort"
	"strings"

	cp "github.com/pingcap-inc/nexuscrm-contract/pkg/controlplane"
)

func listApprovalProcessManagedBusinessKeys(ctx context.Context, reader cp.ComponentRowReader, request cp.ComponentManagedSetRequest) ([]cp.ComponentLiveBusinessKey, error) {
	if reader == nil {
		return nil, fmt.Errorf("approval process live-key row reader is required")
	}
	if request.PackName == "" || strings.TrimSpace(request.PackName) != request.PackName {
		return nil, fmt.Errorf("pack name %q is not canonical", request.PackName)
	}
	if request.SourceOwner != "" {
		return nil, fmt.Errorf("pack-owned approval process set must not declare source owner %q", request.SourceOwner)
	}
	if request.Kind != cp.ComponentKindApprovalProcess {
		return nil, fmt.Errorf("component kind = %q, want %q", request.Kind, cp.ComponentKindApprovalProcess)
	}
	rows, err := reader.ReadRows(ctx, cp.ComponentRowQuery{
		Table: approvalProcessDefinitionTable, Columns: []string{"DeveloperName", "TableEnumOrId", "OwnerPack"},
		Equal: cp.ComponentRow{"OwnerPack": request.PackName},
	})
	if err != nil {
		return nil, fmt.Errorf("read owner-scoped ProcessDefinition rows for %s: %w", request.PackName, err)
	}
	keys := make([]cp.ComponentLiveBusinessKey, 0, len(rows))
	seen := make(map[string]struct{}, len(rows))
	for _, row := range rows {
		developerName, err := approvalProcessManagedRowString(row, "DeveloperName", true)
		if err != nil {
			return nil, err
		}
		objectAPIName, err := approvalProcessManagedRowString(row, "TableEnumOrId", true)
		if err != nil {
			return nil, err
		}
		ownerPack, err := approvalProcessManagedRowString(row, "OwnerPack", true)
		if err != nil {
			return nil, err
		}
		if ownerPack != request.PackName {
			return nil, fmt.Errorf("ProcessDefinition %s owner %q escaped owner-scoped query for %q", developerName, ownerPack, request.PackName)
		}
		if !metadataDeploySafeIdentifier.MatchString(objectAPIName) || !metadataDeploySafeIdentifier.MatchString(developerName) {
			return nil, fmt.Errorf("ProcessDefinition has non-canonical business key %q/%q", objectAPIName, developerName)
		}
		businessKey := objectAPIName + "/" + developerName
		folded := strings.ToLower(businessKey)
		if _, duplicate := seen[folded]; duplicate {
			return nil, fmt.Errorf("approval process live business key %q is duplicated case-insensitively", businessKey)
		}
		seen[folded] = struct{}{}
		keys = append(keys, cp.ComponentLiveBusinessKey{BusinessKey: businessKey})
	}
	sort.Slice(keys, func(i, j int) bool { return keys[i].BusinessKey < keys[j].BusinessKey })
	return keys, nil
}
