package walletapiimp

import (
	"testing"

	"github.com/tech/sendico/pkg/discovery"
	connectorv1 "github.com/tech/sendico/pkg/proto/connector/v1"
	"google.golang.org/protobuf/types/known/structpb"
)

func TestFilterCryptoGateways_DedupesByInvokeURI(t *testing.T) {
	gateways := []discovery.GatewaySummary{
		{
			ID:              "gw-low",
			Rail:            "CRYPTO",
			Healthy:         true,
			InvokeURI:       "dev-tron-gateway:50071",
			Network:         "TRON_MAINNET",
			RoutingPriority: 10,
		},
		{
			ID:              "gw-high",
			Rail:            "CRYPTO",
			Healthy:         true,
			InvokeURI:       "dev-tron-gateway:50071",
			Network:         "TRON_NILE",
			RoutingPriority: 20,
		},
		{
			ID:              "gw-chain",
			Rail:            "CRYPTO",
			Healthy:         true,
			InvokeURI:       "dev-chain-gateway:50070",
			Network:         "ARBITRUM_SEPOLIA",
			RoutingPriority: 5,
		},
		{
			ID:              "gw-unhealthy",
			Rail:            "CRYPTO",
			Healthy:         false,
			InvokeURI:       "dev-unhealthy:50070",
			Network:         "TRON_MAINNET",
			RoutingPriority: 99,
		},
	}

	filtered := filterCryptoGateways(gateways)
	if len(filtered) != 2 {
		t.Fatalf("expected 2 filtered gateways, got %d", len(filtered))
	}

	byInvoke := map[string]discovery.GatewaySummary{}
	for _, gw := range filtered {
		byInvoke[gw.InvokeURI] = gw
	}

	tron, ok := byInvoke["dev-tron-gateway:50071"]
	if !ok {
		t.Fatalf("expected tron gateway entry")
	}
	if tron.ID != "gw-high" {
		t.Fatalf("expected higher-priority duplicate to win, got %q", tron.ID)
	}

	if _, ok := byInvoke["dev-chain-gateway:50070"]; !ok {
		t.Fatalf("expected chain gateway entry")
	}
}

func TestDedupeAccountsByWalletRef(t *testing.T) {
	detailsA, err := structpb.NewStruct(map[string]interface{}{"wallet_ref": "wallet-3"})
	if err != nil {
		t.Fatalf("build provider details: %v", err)
	}
	detailsB, err := structpb.NewStruct(map[string]interface{}{"wallet_ref": "wallet-3"})
	if err != nil {
		t.Fatalf("build provider details: %v", err)
	}

	accounts := []*connectorv1.Account{
		{Ref: &connectorv1.AccountRef{AccountId: "wallet-1"}},
		{Ref: &connectorv1.AccountRef{AccountId: "wallet-1"}}, // duplicate
		{Ref: &connectorv1.AccountRef{AccountId: "wallet-2"}},
		{ProviderDetails: detailsA},
		{ProviderDetails: detailsB},                   // duplicate via provider_details.wallet_ref
		{Ref: &connectorv1.AccountRef{AccountId: ""}}, // kept: missing ref
		nil, // ignored
	}

	deduped := dedupeAccountsByWalletRef(accounts)
	if len(deduped) != 4 {
		t.Fatalf("expected 4 accounts after dedupe, got %d", len(deduped))
	}

	seen := map[string]int{}
	for _, acc := range deduped {
		if acc == nil {
			t.Fatalf("deduped account should never be nil")
		}
		ref := accountWalletRef(acc)
		seen[ref]++
	}

	if seen["wallet-1"] != 1 {
		t.Fatalf("expected wallet-1 once, got %d", seen["wallet-1"])
	}
	if seen["wallet-2"] != 1 {
		t.Fatalf("expected wallet-2 once, got %d", seen["wallet-2"])
	}
	if seen["wallet-3"] != 1 {
		t.Fatalf("expected wallet-3 once, got %d", seen["wallet-3"])
	}
	if seen[""] != 1 {
		t.Fatalf("expected one account with missing wallet ref, got %d", seen[""])
	}
}
