package records

import (
	"context"
	"fmt"
	"time"

	"github.com/nexuscrm/kernel/pkg/formula"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
)

func cloneRecord(in models.Record) models.Record {
	if in == nil {
		return nil
	}
	out := make(models.Record, len(in))
	for k, v := range in {
		out[k] = v
	}
	return out
}

// cloneSObject preserves the compatibility name for existing engine callers.
// New application-neutral paths should use cloneRecord.
func cloneSObject(in models.SObject) models.SObject {
	return cloneRecord(in)
}

// buildUserContext builds the formula evaluation context for $User, $Profile,
// and $UserRole merge fields, plus platform permission metadata used by
// validation rules.
//
// Salesforce-modeled formula globals (__User, __Profile, __UserRole) are
// sourced via formula.BuildFormulaUserContext - the SINGLE read path shared
// with flow formulas. Both consumers MUST resolve $User/$Profile/$UserRole
// against the same UserSession token so that a single save transaction sees
// identical merge-field values in validation rules and flow formulas. See
// pkg/formula/user_context.go and CLAUDE.md "Salesforce Boundary".
//
// Permissions (__SystemPermissions / __CustomPermissions) are platform
// metadata - not Salesforce $globals - and stay here. They are consumed by
// validation rules and assertions only.
func (ps *PersistenceService) buildUserContext(ctx context.Context, currentUser *models.UserSession) map[string]interface{} {
	if currentUser == nil {
		return nil
	}
	userCtx := formula.BuildFormulaUserContext(currentUser)
	if userCtx == nil {
		userCtx = map[string]interface{}{}
	}
	userCtx[constants.FormulaContextSystemContext] = constants.FormulaSystemContextFromContext(ctx)

	systemPerms := map[string]bool{}
	customPerms := map[string]bool{}
	if ps.permissions != nil {
		if effective, err := ps.permissions.GetEffectiveSystemPermissions(ctx, currentUser.ID, currentUser.ProfileID); err == nil && effective != nil {
			systemPerms = effective
		}
		if effective, err := ps.permissions.GetEffectiveCustomPermissions(ctx, currentUser.ID, currentUser.ProfileID); err == nil && effective != nil {
			customPerms = effective
		}
	}
	userCtx[constants.ContextKeySystemPermissions] = systemPerms
	userCtx[constants.ContextKeyCustomPermissions] = customPerms

	return userCtx
}

// valToString converts any value to string for audit logging
func (ps *PersistenceService) valToString(val interface{}) string {
	if val == nil {
		return ""
	}
	switch v := val.(type) {
	case time.Time:
		return v.Format(time.RFC3339)
	case *time.Time:
		if v != nil {
			return v.Format(time.RFC3339)
		}
		return ""
	case fmt.Stringer:
		return v.String()
	default:
		return fmt.Sprintf("%v", val)
	}
}

// Helper to safely get user ID
func getUserID(user *models.UserSession) string {
	if user == nil {
		return "system"
	}
	return user.ID
}

// requestIDFromCtx extracts the request ID from context for log correlation.
func requestIDFromCtx(ctx context.Context) string {
	if id, ok := ctx.Value(constants.ContextKeyRequestID).(string); ok {
		return id
	}
	return ""
}
