package events

import (
	"context"
	"fmt"
	"strconv"

	"github.com/google/uuid"
	"github.com/nexuscrm/shared/pkg/constants"
)

// LineageFromContext returns (chainID, chainDepth, isFresh) for the current context.
//
// If ctx carries a non-empty AfterSave chain id, the chain is inherited:
// the same chainID is returned with chainDepth = parent_depth + 1, isFresh = false.
//
// Otherwise a fresh chainID is minted as a UUID, chainDepth = 0, isFresh = true.
//
// The returned values are the ones that MUST be written into
// RecordEventPayload.Metadata before repo.Enqueue. This function is the
// single mint/inherit path — no other file may generate or derive chain lineage.
func LineageFromContext(ctx context.Context) (chainID string, chainDepth int, isFresh bool) {
	if v := ctx.Value(constants.ContextKeyAfterSaveChainID); v != nil {
		if id, ok := v.(string); ok && id != "" {
			depth := 0
			if dv := ctx.Value(constants.ContextKeyAfterSaveChainDepth); dv != nil {
				if ds, ok := dv.(string); ok {
					depth, _ = strconv.Atoi(ds)
				}
			}
			return id, depth + 1, false
		}
	}
	return uuid.New().String(), 0, true
}

// AfterSaveChainIDFromContext returns the AfterSave chain id already present
// on ctx, or "" when there is none. Unlike LineageFromContext it NEVER mints —
// read-only consumers (e.g. the approval submit-lineage dedup probe) must not
// fabricate lineage; LineageFromContext stays the single mint/inherit path.
func AfterSaveChainIDFromContext(ctx context.Context) string {
	if v := ctx.Value(constants.ContextKeyAfterSaveChainID); v != nil {
		if id, ok := v.(string); ok {
			return id
		}
	}
	return ""
}

// WithLineage returns a copy of ctx carrying the given chain lineage as typed
// constants.ContextKey values. Used by processEventAtomic's restore loop
// (indirectly via the generic Metadata→ctx restore) and by tests that need to
// simulate an AfterSave execution context.
func WithLineage(ctx context.Context, chainID string, chainDepth int) context.Context {
	ctx = context.WithValue(ctx, constants.ContextKeyAfterSaveChainID, chainID)
	ctx = context.WithValue(ctx, constants.ContextKeyAfterSaveChainDepth, fmt.Sprintf("%d", chainDepth))
	return ctx
}
