package automation

import (
	"strings"

	"github.com/nexuscrm/shared/pkg/models"
)

func initializeFlowContext(flowMeta *models.FlowMetadata, inputs map[string]interface{}, processType string) map[string]interface{} {
	ctx := make(map[string]interface{})

	// Initialize variables with defaults
	for _, variable := range flowMeta.Variables {
		if variable.Value != nil {
			ctx[variable.Name] = variable.Value
		}
	}

	// Apply input values
	for key, value := range inputs {
		ctx[key] = value
	}

	// Workflow processType flows declare myVariable_current/myVariable_old as
	// input SObject variables with no default. Alias them to $Record/$Record__Old
	// so every field reference on these variables resolves correctly at runtime.
	bindWorkflowRecordAliases(flowMeta, ctx, processType)

	return ctx
}

func bindWorkflowRecordAliases(flowMeta *models.FlowMetadata, ctx map[string]interface{}, processType string) {
	if flowMeta == nil || !strings.EqualFold(processType, "Workflow") {
		return
	}
	for _, v := range flowMeta.Variables {
		if strings.EqualFold(v.Name, "myVariable_current") {
			ctx[v.Name] = ctx["$Record"]
		} else if strings.EqualFold(v.Name, "myVariable_old") {
			ctx[v.Name] = ctx["$Record__Old"]
		}
	}
}

func cloneFlowContextData(src map[string]interface{}) map[string]interface{} {
	if src == nil {
		return nil
	}
	cloned := make(map[string]interface{}, len(src))
	for key, value := range src {
		cloned[key] = cloneFlowContextValue(value)
	}
	return cloned
}

func cloneFlowContextValue(value interface{}) interface{} {
	switch v := value.(type) {
	case models.SObject:
		cloned := make(models.SObject, len(v))
		for key, inner := range v {
			cloned[key] = cloneFlowContextValue(inner)
		}
		return cloned
	case map[string]interface{}:
		cloned := make(map[string]interface{}, len(v))
		for key, inner := range v {
			cloned[key] = cloneFlowContextValue(inner)
		}
		return cloned
	case []models.SObject:
		cloned := make([]models.SObject, len(v))
		for i, inner := range v {
			cloned[i] = cloneFlowContextValue(inner).(models.SObject)
		}
		return cloned
	case []map[string]interface{}:
		cloned := make([]map[string]interface{}, len(v))
		for i, inner := range v {
			cloned[i] = cloneFlowContextValue(inner).(map[string]interface{})
		}
		return cloned
	case []interface{}:
		cloned := make([]interface{}, len(v))
		for i, inner := range v {
			cloned[i] = cloneFlowContextValue(inner)
		}
		return cloned
	case []string:
		return append([]string(nil), v...)
	case []bool:
		return append([]bool(nil), v...)
	case []int:
		return append([]int(nil), v...)
	case []int64:
		return append([]int64(nil), v...)
	case []float64:
		return append([]float64(nil), v...)
	default:
		return value
	}
}
