package gateway

import (
	"testing"

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

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

func TestValidateCardPayoutRequest_Errors(t *testing.T) {
	baseCfg := testProviderConfig()
	cases := []struct {
		name     string
		mutate   func(*mntxv1.CardPayoutRequest)
		config   func(provider.Config) provider.Config
		expected string
	}{
		{
			name:     "missing_operation_identity",
			mutate:   func(r *mntxv1.CardPayoutRequest) { r.PayoutId = "" },
			expected: "missing_operation_ref",
		},
		{
			name:     "missing_parent_payment_ref",
			mutate:   func(r *mntxv1.CardPayoutRequest) { r.ParentPaymentRef = "" },
			expected: "missing_parent_payment_ref",
		},
		{
			name: "both_operation_and_payout_identity",
			mutate: func(r *mntxv1.CardPayoutRequest) {
				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.CardPayoutRequest) { r.CustomerId = "" },
			expected: "missing_customer_id",
		},
		{
			name:     "missing_customer_ip",
			mutate:   func(r *mntxv1.CardPayoutRequest) { r.CustomerIp = "" },
			expected: "missing_customer_ip",
		},
		{
			name:     "invalid_amount",
			mutate:   func(r *mntxv1.CardPayoutRequest) { r.AmountMinor = 0 },
			expected: "invalid_amount",
		},
		{
			name:     "missing_currency",
			mutate:   func(r *mntxv1.CardPayoutRequest) { r.Currency = "" },
			expected: "missing_currency",
		},
		{
			name:   "unsupported_currency",
			mutate: func(r *mntxv1.CardPayoutRequest) { r.Currency = "EUR" },
			config: func(cfg provider.Config) provider.Config {
				cfg.AllowedCurrencies = []string{"USD"}
				return cfg
			},
			expected: "unsupported_currency",
		},
		{
			name:     "missing_card_pan",
			mutate:   func(r *mntxv1.CardPayoutRequest) { r.CardPan = "" },
			expected: "missing_card_pan",
		},
		{
			name:     "invalid_card_pan_crc",
			mutate:   func(r *mntxv1.CardPayoutRequest) { r.CardPan = "4111111111111112" },
			expected: "invalid_card_pan_crc",
		},
		{
			name:     "missing_card_holder",
			mutate:   func(r *mntxv1.CardPayoutRequest) { r.CardHolder = "" },
			expected: "missing_card_holder",
		},
		{
			name:     "invalid_expiry_month",
			mutate:   func(r *mntxv1.CardPayoutRequest) { r.CardExpMonth = 13 },
			expected: "invalid_expiry_month",
		},
		{
			name:     "invalid_expiry_year",
			mutate:   func(r *mntxv1.CardPayoutRequest) { r.CardExpYear = 0 },
			expected: "invalid_expiry_year",
		},
		{
			name:   "missing_customer_country_when_required",
			mutate: func(r *mntxv1.CardPayoutRequest) { r.CustomerCountry = "" },
			config: func(cfg provider.Config) provider.Config {
				cfg.RequireCustomerAddress = true
				return cfg
			},
			expected: "missing_customer_country",
		},
	}

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