package quote_computation_service

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

	"github.com/tech/sendico/payments/storage/model"
	moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
)

type selectorGatewayRegistry struct {
	items []*model.GatewayInstanceDescriptor
}

func (s selectorGatewayRegistry) List(context.Context) ([]*model.GatewayInstanceDescriptor, error) {
	return s.items, nil
}

func TestResolveStepGateways_FallsBackToInvokeURI(t *testing.T) {
	svc := New(nil, WithGatewayRegistry(selectorGatewayRegistry{
		items: []*model.GatewayInstanceDescriptor{
			{
				ID:         "aaa",
				InstanceID: "inst-a",
				InvokeURI:  "grpc://gw-a:50051",
				Rail:       discovery.RailCrypto,
				Network:    "TRON",
				Currencies: []string{"USDT"},
				Capabilities: model.RailCapabilities{
					CanPayOut: true,
				},
				IsEnabled: true,
			},
			{
				ID:         "bbb",
				InstanceID: "inst-b",
				InvokeURI:  "grpc://gw-b:50051",
				Rail:       discovery.RailCrypto,
				Network:    "TRON",
				Currencies: []string{"USDT"},
				Capabilities: model.RailCapabilities{
					CanPayOut: true,
				},
				IsEnabled: true,
			},
		},
	}))
	steps := []*QuoteComputationStep{
		{
			StepID:           "i0.destination",
			Rail:             discovery.RailCrypto,
			Operation:        discovery.RailOperationExternalCredit,
			GatewayID:        "legacy-id",
			InstanceID:       "legacy-instance",
			GatewayInvokeURI: "grpc://gw-b:50051",
			Amount:           &moneyv1.Money{Currency: "USDT", Amount: "10"},
		},
	}

	if err := svc.resolveStepGateways(context.Background(), steps, "TRON"); err != nil {
		t.Fatalf("resolveStepGateways returned error: %v", err)
	}
	if got, want := steps[0].GatewayID, "bbb"; got != want {
		t.Fatalf("unexpected gateway_id: got=%q want=%q", got, want)
	}
	if got, want := steps[0].InstanceID, "inst-b"; got != want {
		t.Fatalf("unexpected instance_id: got=%q want=%q", got, want)
	}
	if got, want := steps[0].GatewayInvokeURI, "grpc://gw-b:50051"; got != want {
		t.Fatalf("unexpected gateway_invoke_uri: got=%q want=%q", got, want)
	}
}

func TestResolveStepGateways_FallsBackToGatewayIDWhenInstanceChanges(t *testing.T) {
	svc := New(nil, WithGatewayRegistry(selectorGatewayRegistry{
		items: []*model.GatewayInstanceDescriptor{
			{
				ID:         "aaa",
				InstanceID: "inst-a",
				InvokeURI:  "grpc://gw-a:50051",
				Rail:       discovery.RailCrypto,
				Network:    "TRON",
				Currencies: []string{"USDT"},
				Capabilities: model.RailCapabilities{
					CanPayOut: true,
				},
				IsEnabled: true,
			},
			{
				ID:         "crypto_rail_gateway_tron",
				InstanceID: "inst-new",
				InvokeURI:  "grpc://gw-tron:50051",
				Rail:       discovery.RailCrypto,
				Network:    "TRON",
				Currencies: []string{"USDT"},
				Capabilities: model.RailCapabilities{
					CanPayOut: true,
				},
				IsEnabled: true,
			},
		},
	}))
	steps := []*QuoteComputationStep{
		{
			StepID:     "i0.destination",
			Rail:       discovery.RailCrypto,
			Operation:  discovery.RailOperationExternalCredit,
			GatewayID:  "crypto_rail_gateway_tron",
			InstanceID: "inst-old",
			Amount:     &moneyv1.Money{Currency: "USDT", Amount: "10"},
		},
	}

	if err := svc.resolveStepGateways(context.Background(), steps, "TRON"); err != nil {
		t.Fatalf("resolveStepGateways returned error: %v", err)
	}
	if got, want := steps[0].GatewayID, "crypto_rail_gateway_tron"; got != want {
		t.Fatalf("unexpected gateway_id: got=%q want=%q", got, want)
	}
	if got, want := steps[0].InstanceID, "inst-new"; got != want {
		t.Fatalf("unexpected instance_id: got=%q want=%q", got, want)
	}
	if got, want := steps[0].GatewayInvokeURI, "grpc://gw-tron:50051"; got != want {
		t.Fatalf("unexpected gateway_invoke_uri: got=%q want=%q", got, want)
	}
}
