// Package taskutil — system_registry.go
//
// v0.28.6: System task function registry.
//
// Built-in Go functions that run as auditable, scheduled tasks instead of
// ad-hoc goroutines. Each function receives a context, the full store set,
// and returns a structured result. The registry is permanent — system
// functions are not replaced by Starlark (v0.29.0). Core platform ops
// must not break from bad user code.
//
// Registration happens at init time from main.go. The executor calls
// Get() to look up a function by name at execution time.
package taskutil

import (
	"context"
	"fmt"
	"sort"
	"sync"

	"chat-switchboard/store"
)

// SystemFunc is the signature for built-in system task functions.
// The function receives a context and the full store set. It returns
// a human-readable result string (logged in the task run) and an error.
type SystemFunc func(ctx context.Context, stores store.Stores) (string, error)

// SystemFuncInfo describes a registered system function.
type SystemFuncInfo struct {
	Name        string `json:"name"`
	Description string `json:"description"`
}

var (
	registryMu sync.RWMutex
	registry   = make(map[string]registryEntry)
)

type registryEntry struct {
	fn          SystemFunc
	description string
}

// RegisterSystemFunc registers a named system function.
// Call during init (before scheduler starts). Not goroutine-safe for writes.
func RegisterSystemFunc(name, description string, fn SystemFunc) {
	registryMu.Lock()
	defer registryMu.Unlock()
	registry[name] = registryEntry{fn: fn, description: description}
}

// GetSystemFunc returns a system function by name.
func GetSystemFunc(name string) (SystemFunc, bool) {
	registryMu.RLock()
	defer registryMu.RUnlock()
	e, ok := registry[name]
	if !ok {
		return nil, false
	}
	return e.fn, true
}

// ListSystemFuncs returns all registered system function names and descriptions.
func ListSystemFuncs() []SystemFuncInfo {
	registryMu.RLock()
	defer registryMu.RUnlock()
	result := make([]SystemFuncInfo, 0, len(registry))
	for name, e := range registry {
		result = append(result, SystemFuncInfo{Name: name, Description: e.description})
	}
	sort.Slice(result, func(i, j int) bool { return result[i].Name < result[j].Name })
	return result
}

// ValidateSystemFunc returns an error if the function name is not registered.
func ValidateSystemFunc(name string) error {
	registryMu.RLock()
	defer registryMu.RUnlock()
	if _, ok := registry[name]; !ok {
		names := make([]string, 0, len(registry))
		for n := range registry {
			names = append(names, n)
		}
		sort.Strings(names)
		return fmt.Errorf("unknown system function %q (available: %v)", name, names)
	}
	return nil
}
