package payment

import (
	"context"
	bizpayment "kra/internal/biz/payment"
	"strings"
	"testing"

	gopayDouyin "github.com/go-pay/gopay/douyin"
	gopayWechatV3 "github.com/go-pay/gopay/wechat/v3"
)

func TestWechatV3RefundRejectsBlankIdentityBeforeClient(t *testing.T) {
	for _, tc := range []struct {
		name string
		req  *bizpayment.PaymentRefundRequest
		want string
	}{
		{name: "blank trade number", req: &bizpayment.PaymentRefundRequest{TradeNo: "  ", RefundNo: "R1"}, want: "out_trade_no"},
		{name: "blank refund number", req: &bizpayment.PaymentRefundRequest{TradeNo: "T1", RefundNo: "  "}, want: "out_refund_no"},
		{name: "invalid amount", req: &bizpayment.PaymentRefundRequest{TradeNo: "T1", RefundNo: "R1", Amount: 2, TotalAmount: 1}, want: "金额"},
	} {
		t.Run(tc.name, func(t *testing.T) {
			_, err := (&wechatV3Adapter{}).Refund(context.Background(), tc.req, nil)
			if err == nil || !strings.Contains(err.Error(), tc.want) {
				t.Fatalf("Refund() error = %v, want %q", err, tc.want)
			}
		})
	}
}

func TestWechatV3RefundIdentityValidation(t *testing.T) {
	valid := func() *gopayWechatV3.RefundOrderResponse {
		return &gopayWechatV3.RefundOrderResponse{
			OutTradeNo:  " T1 ",
			OutRefundNo: " R1 ",
			RefundId:    " WX-R1 ",
		}
	}
	refundID, err := validateWechatV3RefundIdentity(valid(), " T1 ", " R1 ")
	if err != nil {
		t.Fatalf("valid refund response: %v", err)
	}
	if refundID != "WX-R1" {
		t.Fatalf("refund id = %q, want %q", refundID, "WX-R1")
	}
	for _, tc := range []struct {
		name string
		edit func(*gopayWechatV3.RefundOrderResponse)
	}{
		{name: "trade number missing", edit: func(r *gopayWechatV3.RefundOrderResponse) { r.OutTradeNo = " " }},
		{name: "trade number mismatch", edit: func(r *gopayWechatV3.RefundOrderResponse) { r.OutTradeNo = "OTHER" }},
		{name: "refund number missing", edit: func(r *gopayWechatV3.RefundOrderResponse) { r.OutRefundNo = " " }},
		{name: "refund number mismatch", edit: func(r *gopayWechatV3.RefundOrderResponse) { r.OutRefundNo = "OTHER" }},
		{name: "provider refund id missing", edit: func(r *gopayWechatV3.RefundOrderResponse) { r.RefundId = " " }},
	} {
		t.Run(tc.name, func(t *testing.T) {
			refund := valid()
			tc.edit(refund)
			if _, err := validateWechatV3RefundIdentity(refund, "T1", "R1"); err == nil {
				t.Fatal("accepted invalid refund identity")
			}
		})
	}
}

func TestDouyinRefundRejectsBlankIdentityBeforeClient(t *testing.T) {
	for _, tc := range []struct {
		name string
		req  *bizpayment.PaymentRefundRequest
		want string
	}{
		{name: "blank trade number", req: &bizpayment.PaymentRefundRequest{TradeNo: "  ", RefundNo: "R1"}, want: "out_trade_no"},
		{name: "blank refund number", req: &bizpayment.PaymentRefundRequest{TradeNo: "T1", RefundNo: "  "}, want: "out_refund_no"},
		{name: "invalid amount", req: &bizpayment.PaymentRefundRequest{TradeNo: "T1", RefundNo: "R1", Amount: 2, TotalAmount: 1}, want: "金额"},
	} {
		t.Run(tc.name, func(t *testing.T) {
			_, err := (&douyinAdapter{}).Refund(context.Background(), tc.req, nil)
			if err == nil || !strings.Contains(err.Error(), tc.want) {
				t.Fatalf("Refund() error = %v, want %q", err, tc.want)
			}
		})
	}
}

func TestDouyinRefundIdentityValidation(t *testing.T) {
	valid := func() *gopayDouyin.Refund {
		return &gopayDouyin.Refund{
			OutTradeNo:  " T1 ",
			OutRefundNo: " R1 ",
			RefundId:    " DY-R1 ",
		}
	}
	refundID, err := validateDouyinRefundIdentity(valid(), " T1 ", " R1 ")
	if err != nil {
		t.Fatalf("valid refund response: %v", err)
	}
	if refundID != "DY-R1" {
		t.Fatalf("refund id = %q, want %q", refundID, "DY-R1")
	}
	for _, tc := range []struct {
		name string
		edit func(*gopayDouyin.Refund)
	}{
		{name: "trade number missing", edit: func(r *gopayDouyin.Refund) { r.OutTradeNo = " " }},
		{name: "trade number mismatch", edit: func(r *gopayDouyin.Refund) { r.OutTradeNo = "OTHER" }},
		{name: "refund number missing", edit: func(r *gopayDouyin.Refund) { r.OutRefundNo = " " }},
		{name: "refund number mismatch", edit: func(r *gopayDouyin.Refund) { r.OutRefundNo = "OTHER" }},
		{name: "provider refund id missing", edit: func(r *gopayDouyin.Refund) { r.RefundId = " " }},
	} {
		t.Run(tc.name, func(t *testing.T) {
			refund := valid()
			tc.edit(refund)
			if _, err := validateDouyinRefundIdentity(refund, "T1", "R1"); err == nil {
				t.Fatal("accepted invalid refund identity")
			}
		})
	}
}
