// Package referenceidentity defines the request-bound authority for logical
// records whose durable identity is owned outside the physical record store.
package referenceidentity

import (
	"context"

	"github.com/nexuscrm/shared/pkg/models"
)

// Disposition identifies who owns one requested reference identity. Unowned
// identities retain the legacy physical-record behavior. Immutable identities
// are resolved only by the bound authority. OwnedMissing identities are in the
// authority's namespace but absent from its immutable revision and must fail
// closed instead of falling back to a physical sidecar row.
type Disposition uint8

const (
	Unowned Disposition = iota
	Immutable
	OwnedMissing
)

// IdentityResolution is the answer for one requested ID. Record is required
// for Immutable and omitted for OwnedMissing and Unowned.
type IdentityResolution struct {
	Disposition Disposition
	Record      models.SObject
}

// Resolution contains per-ID answers. A requested ID absent from Identities is
// Unowned. Per-ID ownership allows Catalog-native and legacy physical IDs of
// the same target object to coexist during migration.
type Resolution struct {
	Identities map[string]IdentityResolution
}

// Authority resolves logical reference identities from one request-bound,
// immutable source. Implementations claim identities, not whole objects or
// individual reference fields.
type Authority interface {
	ResolveReferenceIdentities(
		context.Context,
		string,
		[]string,
		[]string,
	) (Resolution, error)
}

type contextKey struct{}

// WithAuthority binds the exact identity authority admitted for this request.
func WithAuthority(ctx context.Context, authority Authority) context.Context {
	if ctx == nil {
		ctx = context.Background()
	}
	if authority == nil {
		return ctx
	}
	return context.WithValue(ctx, contextKey{}, authority)
}

// FromContext returns the request-bound identity authority, when present.
func FromContext(ctx context.Context) (Authority, bool) {
	if ctx == nil {
		return nil, false
	}
	authority, ok := ctx.Value(contextKey{}).(Authority)
	return authority, ok && authority != nil
}
