package graph_path_finder

import (
	"github.com/tech/sendico/pkg/discovery"
	"testing"
)

func TestFind_NetworkFiltersEdges(t *testing.T) {
	finder := New()

	path, err := finder.Find(FindInput{
		SourceRail:      discovery.RailCrypto,
		DestinationRail: discovery.RailCardPayout,
		Network:         "TRON",
		Edges: []Edge{
			{FromRail: discovery.RailCrypto, ToRail: discovery.RailLedger, Network: "ETH"},
			{FromRail: discovery.RailCrypto, ToRail: discovery.RailLedger, Network: "TRON"},
			{FromRail: discovery.RailLedger, ToRail: discovery.RailCardPayout, Network: "TRON"},
		},
	})
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	assertPathRails(t, path, []string{"CRYPTO", "LEDGER", "CARD"})
	if got, want := path.Edges[0].Network, "TRON"; got != want {
		t.Fatalf("unexpected first edge network: got=%q want=%q", got, want)
	}
}

func TestFind_PrefersExactNetworkOverWildcard(t *testing.T) {
	finder := New()

	path, err := finder.Find(FindInput{
		SourceRail:      discovery.RailCrypto,
		DestinationRail: discovery.RailCardPayout,
		Network:         "TRON",
		Edges: []Edge{
			{FromRail: discovery.RailCrypto, ToRail: discovery.RailLedger, Network: ""},
			{FromRail: discovery.RailLedger, ToRail: discovery.RailCardPayout, Network: ""},
			{FromRail: discovery.RailCrypto, ToRail: discovery.RailProviderSettlement, Network: "TRON"},
			{FromRail: discovery.RailProviderSettlement, ToRail: discovery.RailCardPayout, Network: "TRON"},
		},
	})
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	assertPathRails(t, path, []string{"CRYPTO", "SETTLEMENT", "CARD"})
}

func TestFind_DeterministicTieBreak(t *testing.T) {
	finder := New()

	path, err := finder.Find(FindInput{
		SourceRail:      discovery.RailCrypto,
		DestinationRail: discovery.RailCardPayout,
		Edges: []Edge{
			{FromRail: discovery.RailCrypto, ToRail: discovery.RailLedger},
			{FromRail: discovery.RailLedger, ToRail: discovery.RailCardPayout},
			{FromRail: discovery.RailCrypto, ToRail: discovery.RailProviderSettlement},
			{FromRail: discovery.RailProviderSettlement, ToRail: discovery.RailCardPayout},
		},
	})
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	// Both routes have equal length; lexical tie-break chooses LEDGER branch.
	assertPathRails(t, path, []string{"CRYPTO", "LEDGER", "CARD"})
}

func TestFind_IgnoresInvalidEdges(t *testing.T) {
	finder := New()

	path, err := finder.Find(FindInput{
		SourceRail:      discovery.RailCrypto,
		DestinationRail: discovery.RailCardPayout,
		Edges: []Edge{
			{FromRail: discovery.RailUnspecified, ToRail: discovery.RailLedger},
			{FromRail: discovery.RailCrypto, ToRail: discovery.RailUnspecified},
			{FromRail: discovery.RailCrypto, ToRail: discovery.RailLedger},
			{FromRail: discovery.RailLedger, ToRail: discovery.RailCardPayout},
		},
	})
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	assertPathRails(t, path, []string{"CRYPTO", "LEDGER", "CARD"})
}
