package bootstrapimpl

import (
	"strings"

	"github.com/nexuscrm/kernel/pkg/schema"
	"github.com/nexuscrm/shared/pkg/constants"
)

// The lookup-reference target cluster stays in bootstrap because the L0
// assertion path (assertLookupReferenceTargetsPopulated in assertions_metadata.go)
// reads the same authoritative target map that the relocated controlplane
// BackfillLookupReferences uses. The type/builder/method are exported so the
// relocated backfill can reach them across the package boundary; logic is
// unchanged from the original in lookup_backfill.go.

type lookupReferenceKey struct {
	objectAPIName string
	fieldAPIName  string
}

// LookupReferenceTargets is the authoritative bootstrap-owned reference_to
// target map for managed lookup/master-detail fields.
type LookupReferenceTargets struct {
	managed map[lookupReferenceKey][]string
}

// LookupReferenceRepairTargets builds the authoritative target map from the
// managed table definitions plus platform-universal field targets.
func LookupReferenceRepairTargets() LookupReferenceTargets {
	targets := LookupReferenceTargets{managed: make(map[lookupReferenceKey][]string)}
	for _, def := range GetManagedTableDefinitions() {
		for _, col := range def.Columns {
			if !isLookupColumnDefinition(col) {
				continue
			}
			targets.managed[lookupReferenceKeyFor(def.TableName, col.Name)] = cleanReferenceTargets(col.ReferenceTo)
		}
	}
	return targets
}

// ReferenceTo resolves the authoritative reference_to targets for a field,
// returning (targets, inScope).
func (t LookupReferenceTargets) ReferenceTo(objectAPIName, fieldAPIName string) ([]string, bool) {
	if targets, ok := t.managed[lookupReferenceKeyFor(objectAPIName, fieldAPIName)]; ok {
		return targets, true
	}
	if target, ok := constants.PlatformReferenceTargetForField(fieldAPIName); ok {
		return []string{target}, true
	}
	return nil, false
}

func lookupReferenceKeyFor(objectAPIName, fieldAPIName string) lookupReferenceKey {
	return lookupReferenceKey{
		objectAPIName: strings.ToLower(strings.TrimSpace(objectAPIName)),
		fieldAPIName:  strings.ToLower(strings.TrimSpace(fieldAPIName)),
	}
}

func isLookupColumnDefinition(col schema.ColumnDefinition) bool {
	if len(cleanReferenceTargets(col.ReferenceTo)) > 0 {
		return true
	}
	if col.IsMasterDetail {
		return true
	}
	switch constants.NormalizeFieldType(col.LogicalType) {
	case constants.FieldTypeReference, constants.FieldTypeMasterDetail:
		return true
	}
	switch constants.NormalizeFieldType(col.Type) {
	case constants.FieldTypeReference, constants.FieldTypeMasterDetail:
		return true
	default:
		return false
	}
}

func cleanReferenceTargets(targets []string) []string {
	cleaned := make([]string, 0, len(targets))
	for _, target := range targets {
		target = strings.TrimSpace(target)
		if target == "" {
			continue
		}
		cleaned = append(cleaned, target)
	}
	return cleaned
}
