package models

import (
	"encoding/json"
	"reflect"
	"testing"
)

func TestFlowExecutionResultLegacyStructShapeRemainsStable(t *testing.T) {
	typeOfResult := reflect.TypeOf(FlowExecutionResult{})
	want := []string{"ActionName", "IsSuccess", "Errors", "OutputValues", "IsCustomError", "IsRetriable"}
	if typeOfResult.NumField() != len(want) {
		t.Fatalf("FlowExecutionResult field count = %d, want %d", typeOfResult.NumField(), len(want))
	}
	for i, name := range want {
		if typeOfResult.Field(i).Name != name {
			t.Fatalf("FlowExecutionResult field %d = %q, want %q", i, typeOfResult.Field(i).Name, name)
		}
	}
}

func TestFlowExecutionOutcomeKeepsLegacyUnkeyedLiteralShape(t *testing.T) {
	outcome := FlowExecutionOutcome{
		&FlowExecutionResult{ActionName: "legacy", IsSuccess: true},
		nil,
	}
	if outcome.Result == nil || outcome.Result.ActionName != "legacy" || outcome.Dependency != nil {
		t.Fatalf("legacy unkeyed FlowExecutionOutcome = %#v", outcome)
	}
}

func TestFlowExecutionTypedOutcomeIsDirectGoOnlyAndDoesNotSerializeDependency(t *testing.T) {
	payload, err := json.Marshal(FlowExecutionTypedOutcome{
		Result:      &FlowExecutionResult{ActionName: "flow", IsSuccess: true},
		ExecutionID: "flow-execution-123",
		Cause: &FlowExecutionCause{
			Code:        "DB_LOCK_WAIT_TIMEOUT",
			Category:    FlowExecutionCauseCategoryConcurrency,
			ElementType: "ActionCall",
			ElementName: "ApplyMappings",
			Retriable:   true,
		},
		Dependency: &FlowExecutionDependencyRequest{
			Kind: FlowDependencyKindIdentityConvergence, ObjectAPIName: "Lead", RecordID: "secret-record",
			ConnectorOwnerKey: "owner", DestinationSlotID: "slot",
		},
	})
	if err != nil {
		t.Fatalf("json.Marshal() error = %v", err)
	}
	if string(payload) != "{}" {
		t.Fatalf("json.Marshal(FlowExecutionTypedOutcome) = %s, want direct-Go-only empty object", payload)
	}
}

func TestFlowExecutionCauseCategoriesRemainStable(t *testing.T) {
	want := map[FlowExecutionCauseCategory]string{
		FlowExecutionCauseCategoryValidation:    "validation",
		FlowExecutionCauseCategoryConcurrency:   "concurrency",
		FlowExecutionCauseCategoryPersistence:   "persistence",
		FlowExecutionCauseCategoryConfiguration: "configuration",
		FlowExecutionCauseCategoryAuthorization: "authorization",
		FlowExecutionCauseCategoryNotFound:      "not_found",
		FlowExecutionCauseCategoryExternal:      "external",
		FlowExecutionCauseCategoryInternal:      "internal",
		FlowExecutionCauseCategoryUnknown:       "unknown",
	}
	for category, value := range want {
		if string(category) != value {
			t.Fatalf("category %q = %q, want %q", category, string(category), value)
		}
	}
}
