package sandbox

// settings_module.go — v0.2.0
//
// The settings module lets extensions read their resolved settings via
// the three-tier cascade: global → team → user, respecting the
// user_overridable flag per setting key.
//
// Always injected (no permission required — a package reads its own settings).
//
// Starlark API:
//   val = settings.get("key")            # returns string, number, bool, or None
//   val = settings.get("key", "default") # returns default if key not set

import (
	"context"

	"go.starlark.net/starlark"
	"go.starlark.net/starlarkstruct"

	"switchboard-core/store"
)

// BuildSettingsModule creates the "settings" Starlark module for a package.
// It resolves the three-tier cascade (global → team → user) respecting
// the user_overridable flag from the package manifest.
func BuildSettingsModule(ctx context.Context, stores store.Stores, packageID, userID, teamID string) *starlarkstruct.Module {
	return MakeModule("settings", starlark.StringDict{
		"get": starlark.NewBuiltin("settings.get", settingsGet(ctx, stores, packageID, userID, teamID)),
	})
}

func settingsGet(ctx context.Context, stores store.Stores, packageID, userID, teamID string) func(*starlark.Thread, *starlark.Builtin, starlark.Tuple, []starlark.Tuple) (starlark.Value, error) {
	return func(_ *starlark.Thread, _ *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) {
		var key string
		var defaultVal starlark.Value = starlark.None
		if err := starlark.UnpackPositionalArgs("settings.get", args, kwargs, 1, &key, &defaultVal); err != nil {
			return nil, err
		}

		if stores.Packages == nil {
			return defaultVal, nil
		}

		// Load global (admin) settings
		globalSettings, err := stores.Packages.GetPackageSettings(ctx, packageID)
		if err != nil {
			globalSettings = nil
		}

		// Load team settings if team context is available
		var teamSettings []byte
		if teamID != "" {
			ts, err := stores.Packages.GetTeamSettings(ctx, packageID, teamID)
			if err == nil {
				teamSettings = ts
			}
		}

		// Load user settings if user context is available
		var userSettings []byte
		if userID != "" {
			pus, err := stores.Packages.GetUserSettings(ctx, packageID, userID)
			if err == nil && pus != nil {
				userSettings = pus.Settings
			}
		}

		// Parse schema from manifest for user_overridable flags
		var schema []store.SettingSchema
		pkg, err := stores.Packages.Get(ctx, packageID)
		if err == nil && pkg != nil && pkg.Manifest != nil {
			schema = store.ParseSettingsSchema(pkg.Manifest)
		}

		// Resolve cascade
		merged := store.ResolveSettings(globalSettings, teamSettings, userSettings, schema)

		val, ok := merged[key]
		if !ok {
			return defaultVal, nil
		}

		sv, err := goToStarlark(val)
		if err != nil {
			return defaultVal, nil
		}
		return sv, nil
	}
}
