package metadata

import (
	"context"
	"strings"
	"testing"

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

func TestValidateFlowVersionAuthoring_ConnectorSource(t *testing.T) {
	t.Parallel()

	validSrc := &models.FlowConnectorSource{
		OwnerPack:   "my-pack",
		ProfileName: "MyProfile",
		ObjectKey:   "contacts",
		ItemsPath:   "$.results",
		ItemIDPath:  "$.id",
	}

	tests := []struct {
		name        string
		version     *models.FlowVersion
		wantErr     bool
		wantMessage string
	}{
		{
			name: "valid connectorSource passes",
			version: &models.FlowVersion{
				Metadata: models.FlowMetadata{
					Start: &models.FlowStart{
						ConnectorSource: validSrc,
					},
				},
			},
			wantErr: false,
		},
		{
			name: "no connectorSource is no-op",
			version: &models.FlowVersion{
				Metadata: models.FlowMetadata{
					Start: &models.FlowStart{Object: "Lead", TriggerType: "RecordAfterSave"},
				},
			},
			wantErr: false,
		},
		{
			name: "nil start is no-op",
			version: &models.FlowVersion{
				Metadata: models.FlowMetadata{},
			},
			wantErr: false,
		},
		{
			name: "connectorSource missing OwnerPack is rejected",
			version: &models.FlowVersion{
				Metadata: models.FlowMetadata{
					Start: &models.FlowStart{
						ConnectorSource: &models.FlowConnectorSource{
							ProfileName: "MyProfile",
							ObjectKey:   "contacts",
							ItemsPath:   "$.results",
							ItemIDPath:  "$.id",
						},
					},
				},
			},
			wantErr:     true,
			wantMessage: "OwnerPack is required",
		},
		{
			name: "connectorSource co-present with Start.Object is rejected",
			version: &models.FlowVersion{
				Metadata: models.FlowMetadata{
					Start: &models.FlowStart{
						Object:          "Contact",
						ConnectorSource: validSrc,
					},
				},
			},
			wantErr:     true,
			wantMessage: "cannot be combined with Start.Object",
		},
	}

	ms := &MetadataService{}
	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			err := ms.validateSupportedAtomicFlowAuthoring(context.Background(), tc.version, nil)
			if tc.wantErr {
				if err == nil {
					t.Fatal("validateSupportedAtomicFlowAuthoring() error = nil, want error")
				}
				if tc.wantMessage != "" && !strings.Contains(err.Error(), tc.wantMessage) {
					t.Fatalf("error = %q, want substring %q", err.Error(), tc.wantMessage)
				}
				return
			}
			if err != nil {
				t.Fatalf("validateSupportedAtomicFlowAuthoring() error = %v, want nil", err)
			}
		})
	}
}

func TestValidateFlowVersionAuthoringUsesTriggerObjectSchemaForFormulaResources(t *testing.T) {
	amount := models.FieldMetadata{APIName: "Amount", Type: constants.FieldTypeCurrency}
	opportunity := &models.ObjectMetadata{
		APIName: "Opportunity",
		Fields:  []models.FieldMetadata{amount},
	}
	ms := &MetadataService{}
	snapshot := &metadataSnapshot{
		schemas:   []*models.ObjectMetadata{opportunity},
		schemaMap: map[string]*models.ObjectMetadata{"opportunity": opportunity},
		fieldMap:  map[string][]models.FieldMetadata{"opportunity": {amount}},
	}
	ms.coreCache.Store(snapshot)
	ms.cache.Store(snapshot)

	version := &models.FlowVersion{Metadata: models.FlowMetadata{
		Start: &models.FlowStart{Object: "Opportunity", TriggerType: "RecordAfterSave"},
		Formulas: []models.FlowFormula{{
			Name: "NextAmount", DataType: "Number", Expression: "$Record.Amount + 1",
		}},
	}}
	if err := ms.validateSupportedAtomicFlowAuthoring(context.Background(), version, nil); err != nil {
		t.Fatalf("record-scoped Formula Resource was rejected: %v", err)
	}
}

func TestFlowVersionFormulaPatchCarriesMetadata(t *testing.T) {
	version := &models.FlowVersion{Metadata: models.FlowMetadata{
		Formulas: []models.FlowFormula{{Name: "Computed", DataType: "Number", Expression: "1 + 1"}},
	}}
	if !flowVersionPatchCarriesMetadata(version) {
		t.Fatal("typed Formula Resource patch bypassed metadata authoring validation")
	}
}
