package gateway

import (
	"testing"

	"github.com/tech/sendico/gateway/aurora/internal/service/provider"
	mntxv1 "github.com/tech/sendico/pkg/proto/gateway/mntx/v1"
)

func TestValidateCardTokenPayoutRequest_Valid(t *testing.T) {
	cfg := testProviderConfig()
	req := validCardTokenPayoutRequest()
	if err := validateCardTokenPayoutRequest(req, cfg); err != nil {
		t.Fatalf("expected no error, got %v", err)
	}
}

func TestValidateCardTokenPayoutRequest_Errors(t *testing.T) {
	baseCfg := testProviderConfig()
	cases := []struct {
		name     string
		mutate   func(*mntxv1.CardTokenPayoutRequest)
		config   func(provider.Config) provider.Config
		expected string
	}{
		{
			name:     "missing_operation_identity",
			mutate:   func(r *mntxv1.CardTokenPayoutRequest) { r.PayoutId = "" },
			expected: "missing_operation_ref",
		},
		{
			name:     "missing_parent_payment_ref",
			mutate:   func(r *mntxv1.CardTokenPayoutRequest) { r.ParentPaymentRef = "" },
			expected: "missing_parent_payment_ref",
		},
		{
			name: "both_operation_and_payout_identity",
			mutate: func(r *mntxv1.CardTokenPayoutRequest) {
				r.PayoutId = "parent-1"
				r.OperationRef = "parent-1:hop_1_card_payout_send"
			},
			expected: "ambiguous_operation_ref",
		},
		{
			name:     "missing_customer_id",
			mutate:   func(r *mntxv1.CardTokenPayoutRequest) { r.CustomerId = "" },
			expected: "missing_customer_id",
		},
		{
			name:     "missing_customer_ip",
			mutate:   func(r *mntxv1.CardTokenPayoutRequest) { r.CustomerIp = "" },
			expected: "missing_customer_ip",
		},
		{
			name:     "invalid_amount",
			mutate:   func(r *mntxv1.CardTokenPayoutRequest) { r.AmountMinor = 0 },
			expected: "invalid_amount",
		},
		{
			name:     "missing_currency",
			mutate:   func(r *mntxv1.CardTokenPayoutRequest) { r.Currency = "" },
			expected: "missing_currency",
		},
		{
			name:   "unsupported_currency",
			mutate: func(r *mntxv1.CardTokenPayoutRequest) { r.Currency = "EUR" },
			config: func(cfg provider.Config) provider.Config {
				cfg.AllowedCurrencies = []string{"USD"}
				return cfg
			},
			expected: "unsupported_currency",
		},
		{
			name:     "missing_card_token",
			mutate:   func(r *mntxv1.CardTokenPayoutRequest) { r.CardToken = "" },
			expected: "missing_card_token",
		},
		{
			name: "missing_customer_city_when_required",
			mutate: func(r *mntxv1.CardTokenPayoutRequest) {
				r.CustomerCountry = "US"
				r.CustomerCity = ""
				r.CustomerAddress = "Main St"
				r.CustomerZip = "12345"
			},
			config: func(cfg provider.Config) provider.Config {
				cfg.RequireCustomerAddress = true
				return cfg
			},
			expected: "missing_customer_city",
		},
	}

	for _, tc := range cases {
		t.Run(tc.name, func(t *testing.T) {
			req := validCardTokenPayoutRequest()
			tc.mutate(req)
			cfg := baseCfg
			if tc.config != nil {
				cfg = tc.config(cfg)
			}
			err := validateCardTokenPayoutRequest(req, cfg)
			requireReason(t, err, tc.expected)
		})
	}
}
