package payment

import (
	"strings"
	"testing"

	"kra/internal/biz"

	gopayAlipay "github.com/go-pay/gopay/alipay"
	"github.com/go-pay/gopay/douyin"
)

func TestWechatV2ResponseRequiresBusinessSuccessCode(t *testing.T) {
	for _, values := range []map[string]string{
		{"return_code": "SUCCESS"},
		{"return_code": "SUCCESS", "result_code": "FAIL"},
		{"return_code": "FAIL", "result_code": "SUCCESS"},
	} {
		if err := validateWechatV2Response(values); err == nil {
			t.Fatalf("accepted unsuccessful response: %#v", values)
		}
	}
	if err := validateWechatV2Response(map[string]string{
		"return_code": "SUCCESS", "result_code": "SUCCESS",
	}); err != nil {
		t.Fatalf("valid response rejected: %v", err)
	}
}

func TestPopulateDouyinPaymentAmountUsesSignedFieldPresence(t *testing.T) {
	amount := &douyin.AmountInfo{Total: 100, PayerTotal: 0, Currency: "CNY", PayerCurrency: "CNY"}
	result := &biz.PaymentResult{}
	if err := populateDouyinPaymentAmount(result, amount, []byte(`{"amount":{"total":100,"payer_total":0,"currency":"CNY","payer_currency":"CNY"}}`)); err != nil {
		t.Fatal(err)
	}
	if !result.AmountBreakdownKnown || result.PayerPaidAmount != 0 || result.CashPaidAmount != 0 || result.DiscountAmount != 100 {
		t.Fatalf("explicit zero payer_total was not preserved: %+v", result)
	}

	result = &biz.PaymentResult{}
	if err := populateDouyinPaymentAmount(result, amount, []byte(`{"amount":{"total":100,"currency":"CNY"}}`)); err != nil {
		t.Fatal(err)
	}
	if result.AmountBreakdownKnown || result.PayerPaidAmount != 0 || result.DiscountAmount != 0 {
		t.Fatalf("missing payer_total was treated as authoritative: %+v", result)
	}

	if err := populateDouyinPaymentAmount(&biz.PaymentResult{}, &douyin.AmountInfo{Total: 100, PayerTotal: 101}, []byte(`{"amount":{"total":100,"payer_total":101}}`)); err == nil {
		t.Fatal("accepted payer_total greater than total")
	}
}

func TestValidateDouyinMerchantIdentity(t *testing.T) {
	config := map[string]any{"merchant_id": "douyin-merchant", "app_id": "douyin-app"}
	if err := validateDouyinMerchantIdentity("douyin-merchant", "douyin-app", config, true); err != nil {
		t.Fatalf("valid identity rejected: %v", err)
	}
	for _, tc := range []struct {
		merchantID string
		appID      string
		requireApp bool
	}{
		{merchantID: "other", appID: "douyin-app", requireApp: true},
		{merchantID: "douyin-merchant", appID: "other", requireApp: true},
		{merchantID: "douyin-merchant", requireApp: true},
	} {
		if err := validateDouyinMerchantIdentity(tc.merchantID, tc.appID, config, tc.requireApp); err == nil {
			t.Fatalf("accepted invalid identity: %+v", tc)
		}
	}
	if err := validateDouyinMerchantIdentity("douyin-merchant", "", config, false); err != nil {
		t.Fatalf("optional query appid rejected: %v", err)
	}
}

func TestAlipayRefundResultValidatesIdentityAndAmount(t *testing.T) {
	req := &biz.PaymentRefundRequest{
		TradeNo: "T-ALIPAY", ProviderTradeNo: "P-ALIPAY", RefundNo: "R-ALIPAY",
		Amount: 123, Currency: "CNY",
	}
	valid := func() *gopayAlipay.TradeRefund {
		return &gopayAlipay.TradeRefund{
			TradeNo: "P-ALIPAY", OutTradeNo: "T-ALIPAY", RefundFee: "1.23", RefundCurrency: "CNY",
		}
	}
	result, err := alipayRefundResult(req, valid(), []byte(`{"ok":true}`))
	if err != nil {
		t.Fatal(err)
	}
	if result.Amount != 123 || result.Currency != "CNY" || result.ProviderTradeNo != "P-ALIPAY" {
		t.Fatalf("unexpected refund result: %+v", result)
	}

	for _, tc := range []struct {
		name   string
		mutate func(*gopayAlipay.TradeRefund)
		want   string
	}{
		{name: "missing merchant order", mutate: func(r *gopayAlipay.TradeRefund) { r.OutTradeNo = "" }, want: "out_trade_no"},
		{name: "mismatched merchant order", mutate: func(r *gopayAlipay.TradeRefund) { r.OutTradeNo = "OTHER" }, want: "out_trade_no"},
		{name: "mismatched provider order", mutate: func(r *gopayAlipay.TradeRefund) { r.TradeNo = "OTHER" }, want: "trade_no"},
		{name: "missing refund fee", mutate: func(r *gopayAlipay.TradeRefund) { r.RefundFee = "" }, want: "refund_fee"},
		{name: "mismatched refund fee", mutate: func(r *gopayAlipay.TradeRefund) { r.RefundFee = "1.22" }, want: "金额不匹配"},
		{name: "mismatched currency", mutate: func(r *gopayAlipay.TradeRefund) { r.RefundCurrency = "USD" }, want: "币种不匹配"},
	} {
		t.Run(tc.name, func(t *testing.T) {
			response := valid()
			tc.mutate(response)
			_, err := alipayRefundResult(req, response, nil)
			if err == nil || !strings.Contains(err.Error(), tc.want) {
				t.Fatalf("invalid response error = %v, want %q", err, tc.want)
			}
		})
	}
}
