package packs

import (
	"context"

	"github.com/nexuscrm/automation"
)

type operationPackSourceOptionsContextKey struct{}

// WithOperationPackSourceOptions binds exact source authority to one control
// plane operation. It intentionally does not mutate process-global defaults:
// callers outside the operation continue to fail closed for release_repo.
func WithOperationPackSourceOptions(ctx context.Context, options PackSourceOptions) context.Context {
	return context.WithValue(ctx, operationPackSourceOptionsContextKey{}, cloneOperationPackSourceOptions(options))
}

// OperationPackSourceOptions returns the exact source authority bound to this
// operation. The returned value is detached from the stored context value so a
// resolver may safely attach request-local schema helpers.
func OperationPackSourceOptions(ctx context.Context) (PackSourceOptions, bool) {
	if ctx == nil {
		return PackSourceOptions{}, false
	}
	options, ok := ctx.Value(operationPackSourceOptionsContextKey{}).(PackSourceOptions)
	if !ok {
		return PackSourceOptions{}, false
	}
	return cloneOperationPackSourceOptions(options), true
}

func cloneOperationPackSourceOptions(options PackSourceOptions) PackSourceOptions {
	cloned := options
	cloned.OfficialRepoSourceRevisions = cloneStringMap(options.OfficialRepoSourceRevisions)
	if options.ReleaseRepoSources != nil {
		cloned.ReleaseRepoSources = make(map[string]ReleaseRepoSource, len(options.ReleaseRepoSources))
		for uri, source := range options.ReleaseRepoSources {
			cloned.ReleaseRepoSources[uri] = source
		}
	}
	if options.ReleaseRepoStoredRevisionSources != nil {
		cloned.ReleaseRepoStoredRevisionSources = make(map[string]ReleaseRepoSource, len(options.ReleaseRepoStoredRevisionSources))
		for key, source := range options.ReleaseRepoStoredRevisionSources {
			cloned.ReleaseRepoStoredRevisionSources[key] = source
		}
	}
	cloned.FlowActionCallRegistrations = append([]automation.FlowActionCallRegistration(nil), options.FlowActionCallRegistrations...)
	cloned.FlowActionCallHandlerImplementations = append([]automation.FlowActionCallHandlerImplementation(nil), options.FlowActionCallHandlerImplementations...)
	return cloned
}

func cloneStringMap(values map[string]string) map[string]string {
	if values == nil {
		return nil
	}
	cloned := make(map[string]string, len(values))
	for key, value := range values {
		cloned[key] = value
	}
	return cloned
}
