package offlinecandidateauthority

import (
	"context"
	"fmt"
	"strings"
	"sync/atomic"
)

type formulaStorageTransitionScopeKey struct{}
type formulaStorageTransitionScope struct {
	active        *atomic.Bool
	packName      string
	packInstallID string
	allFields     bool
	transitions   map[string]struct{}
}

type stoppedSourceSetWitness struct{}

// StoppedSourceSetAuthority is an operation-local capability for the stopped
// source-set path. The unexported witness and Go's internal-package boundary
// prevent module consumers from minting it.
type StoppedSourceSetAuthority struct {
	witness *stoppedSourceSetWitness
}

// NewStoppedSourceSetAuthority creates the capability used by the
// control-plane-owned stopped source-set entrypoint.
func NewStoppedSourceSetAuthority() StoppedSourceSetAuthority {
	return StoppedSourceSetAuthority{witness: &stoppedSourceSetWitness{}}
}

// Valid reports whether the authority was minted by this internal package.
func (authority StoppedSourceSetAuthority) Valid() bool {
	return authority.witness != nil
}

type FormulaStorageTransition struct {
	ObjectAPIName string
	FieldAPIName  string
}

// RunWithStoppedSourceSetApplyScope binds one prepared candidate execution
// while Runtime is stopped. It carries the candidate incarnation to components
// without changing the active InstalledPack compatibility projection. The
// applying component still owns the exact object/field transition list.
func RunWithStoppedSourceSetApplyScope(ctx context.Context, packName, packInstallID string, run func(context.Context) error) error {
	if run == nil {
		return fmt.Errorf("stopped source-set formula storage callback is required")
	}
	packName = strings.TrimSpace(packName)
	if packName == "" {
		return fmt.Errorf("stopped source-set formula storage pack name is required")
	}
	packInstallID = strings.TrimSpace(packInstallID)
	if packInstallID == "" {
		return fmt.Errorf("stopped source-set candidate installation identity is required")
	}
	if ctx == nil {
		ctx = context.Background()
	}
	if formulaStorageTransitionScopeFromContext(ctx) != nil {
		return fmt.Errorf("stopped source-set formula storage scope is already active")
	}
	active := &atomic.Bool{}
	active.Store(true)
	defer active.Store(false)
	return run(context.WithValue(
		ctx,
		formulaStorageTransitionScopeKey{},
		&formulaStorageTransitionScope{active: active, packName: packName, packInstallID: packInstallID, allFields: true},
	))
}

// RunWithFormulaStorageTransitionScope binds the narrowly scoped execution
// authority used by the Catalog-owned offline-candidate entrypoint. Go's
// internal-package boundary prevents module consumers from minting this scope;
// the repository route guard pins its only production caller.
//
// This function does not stop Runtime by itself. Its caller is the explicit
// stopped-Runtime deployment operation, which owns that external lifecycle
// precondition and the exact candidate receipt.
func RunWithFormulaStorageTransitionScope(ctx context.Context, packName string, transitions []FormulaStorageTransition, run func(context.Context) error) error {
	if run == nil {
		return fmt.Errorf("stopped-Runtime formula storage transition callback is required")
	}
	packName = strings.TrimSpace(packName)
	if packName == "" {
		return fmt.Errorf("stopped-Runtime formula storage transition pack name is required")
	}
	allowed := make(map[string]struct{}, len(transitions))
	for _, transition := range transitions {
		key := formulaStorageTransitionKey(transition.ObjectAPIName, transition.FieldAPIName)
		if key == "" {
			return fmt.Errorf("stopped-Runtime formula storage transition requires canonical object and field names")
		}
		allowed[key] = struct{}{}
	}
	if len(allowed) == 0 {
		return fmt.Errorf("stopped-Runtime formula storage transition requires at least one exact field")
	}
	if ctx == nil {
		ctx = context.Background()
	}
	if formulaStorageTransitionScopeFromContext(ctx) != nil {
		return fmt.Errorf("stopped-Runtime formula storage transition scope is already active")
	}
	active := &atomic.Bool{}
	active.Store(true)
	defer active.Store(false)
	return run(context.WithValue(
		ctx,
		formulaStorageTransitionScopeKey{},
		&formulaStorageTransitionScope{active: active, packName: packName, transitions: allowed},
	))
}

// FormulaStorageTransitionAllowed reports whether ctx belongs to the currently
// executing materialization of the named offline-candidate pack. The scope is
// revoked as soon as that one internal apply returns, so a retained context
// cannot authorize later work.
func FormulaStorageTransitionAllowed(ctx context.Context, packName, objectAPIName, fieldAPIName string) bool {
	scope := formulaStorageTransitionScopeFromContext(ctx)
	if scope == nil ||
		scope.active == nil || !scope.active.Load() ||
		!strings.EqualFold(scope.packName, strings.TrimSpace(packName)) {
		return false
	}
	if scope.allFields {
		return true
	}
	_, ok := scope.transitions[formulaStorageTransitionKey(objectAPIName, fieldAPIName)]
	return ok
}

// StoppedSourceSetApplyOnly reports whether ctx belongs to the currently
// executing stopped source-set mutation. The scope is revoked when that one
// internal apply returns.
func StoppedSourceSetApplyOnly(ctx context.Context, packName string) bool {
	scope := formulaStorageTransitionScopeFromContext(ctx)
	return scope != nil &&
		scope.active != nil && scope.active.Load() &&
		scope.allFields &&
		strings.EqualFold(scope.packName, strings.TrimSpace(packName))
}

// StoppedSourceSetPackInstallID returns the operation-local candidate
// incarnation for the currently executing stopped source-set pack. Candidate
// components must use this identity instead of reading the active compatibility
// projection while the replacement is still being prepared.
func StoppedSourceSetPackInstallID(ctx context.Context, packName string) (string, bool) {
	scope := formulaStorageTransitionScopeFromContext(ctx)
	if scope == nil ||
		scope.active == nil || !scope.active.Load() ||
		!scope.allFields ||
		!strings.EqualFold(scope.packName, strings.TrimSpace(packName)) ||
		strings.TrimSpace(scope.packInstallID) == "" {
		return "", false
	}
	return scope.packInstallID, true
}

func formulaStorageTransitionKey(objectAPIName, fieldAPIName string) string {
	objectAPIName = strings.ToLower(strings.TrimSpace(objectAPIName))
	fieldAPIName = strings.ToLower(strings.TrimSpace(fieldAPIName))
	if objectAPIName == "" || fieldAPIName == "" {
		return ""
	}
	return objectAPIName + "\x00" + fieldAPIName
}

func formulaStorageTransitionScopeFromContext(ctx context.Context) *formulaStorageTransitionScope {
	if ctx == nil {
		return nil
	}
	scope, _ := ctx.Value(formulaStorageTransitionScopeKey{}).(*formulaStorageTransitionScope)
	return scope
}
