package connector

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

func TestConnectorFieldMappingProjectionOnlyChangesDurableJSON(t *testing.T) {
	base := ConnectorFieldMappingInput{
		Source:       "companion",
		SourceObject: "contacts",
		TargetObject: "Lead",
		ActionType:   "inbound",
		SourceField:  "legacy_source_id",
		Direction:    DirectionInbound,
	}

	ordinaryJSON, err := json.Marshal(base)
	if err != nil {
		t.Fatalf("marshal ordinary row: %v", err)
	}
	projection := base
	projection.ProjectionOnly = true
	projectionJSON, err := json.Marshal(projection)
	if err != nil {
		t.Fatalf("marshal projection-only row: %v", err)
	}

	if bytes.Equal(ordinaryJSON, projectionJSON) {
		t.Fatalf("projection-only row reused ordinary durable JSON: %s", ordinaryJSON)
	}
	wantOrdinaryJSON := `{"Source":"companion","SourceObject":"contacts","TargetObject":"Lead","ActionType":"inbound","SourceField":"legacy_source_id","TargetField":"","Direction":"inbound","TransformExpression":"","ConflictPolicy":"","DefaultValue":"","SortOrder":0}`
	if string(ordinaryJSON) != wantOrdinaryJSON {
		t.Fatalf("ordinary row durable JSON changed:\n got: %s\nwant: %s", ordinaryJSON, wantOrdinaryJSON)
	}
	if !bytes.Contains(projectionJSON, []byte(`"ProjectionOnly":true`)) {
		t.Fatalf("projection-only marker missing from durable JSON: %s", projectionJSON)
	}
}

func TestValidateConnectorFieldMappingInputSetRejectsWriteAndProjectionDuplicateSourceTuple(t *testing.T) {
	ordinary := ConnectorFieldMappingInput{
		Source:       "companion",
		SourceObject: "contacts",
		TargetObject: "Lead",
		ActionType:   "inbound",
		SourceField:  "legacy_source_id",
		TargetField:  "LegacySourceId__c",
		Direction:    DirectionInbound,
	}
	projection := ordinary
	projection.TargetField = ""
	projection.ProjectionOnly = true

	if err := ValidateConnectorFieldMappingInputSet([]ConnectorFieldMappingInput{ordinary, projection}); err == nil {
		t.Fatal("write and projection rows with the same source business key must be rejected")
	}
}

func TestValidateConnectorFieldMappingInputSetAllowsDistinctProjectionOnlySources(t *testing.T) {
	rows := []ConnectorFieldMappingInput{
		{
			Source:         "companion",
			SourceObject:   "contacts",
			TargetObject:   "Lead",
			ActionType:     "inbound",
			SourceField:    "legacy_lead_id",
			Direction:      DirectionInbound,
			ProjectionOnly: true,
		},
		{
			Source:         "companion",
			SourceObject:   "contacts",
			TargetObject:   "Lead",
			ActionType:     "inbound",
			SourceField:    "legacy_contact_id",
			Direction:      DirectionInbound,
			ProjectionOnly: true,
		},
	}

	if err := ValidateConnectorFieldMappingInputSet(rows); err != nil {
		t.Fatalf("distinct projection-only source fields must not collide on a blank target: %v", err)
	}
}
