package wechat

import (
	"encoding/json"
	"testing"
	"time"
)

func TestUploadVirtualShippingPayload(t *testing.T) {
	req := &uploadShippingInfoRequest{
		OrderKey:      orderKey{OrderNumberType: 2, TransactionID: "4200001234567890"},
		LogisticsType: 3,
		DeliveryMode:  1,
		ShippingList:  []shippingItem{{ItemDesc: "虚拟礼包*1"}},
		UploadTime:    time.Date(2025, 1, 2, 3, 4, 5, 0, time.UTC).Format(time.RFC3339),
	}
	b, err := json.Marshal(req)
	if err != nil {
		t.Fatalf("marshal error: %v", err)
	}
	s := string(b)
	if !containsAll(s, []string{"\"order_number_type\":2", "\"transaction_id\":\"4200001234567890\"", "\"logistics_type\":3", "\"delivery_mode\":1", "\"item_desc\":\"虚拟礼包*1\""}) {
		t.Fatalf("payload missing fields: %s", s)
	}
	if containsAny(s, []string{"tracking_no", "express_company"}) {
		t.Fatalf("payload should not include tracking fields for virtual: %s", s)
	}
}

func TestUploadVirtualShippingPayloadWithOutTradeNo(t *testing.T) {
	req := &uploadShippingInfoRequest{
		OrderKey:      orderKey{OrderNumberType: 1, OutTradeNo: "O202501010001"},
		LogisticsType: 3,
		DeliveryMode:  1,
		ShippingList:  []shippingItem{{ItemDesc: "订单O202501010001"}},
		UploadTime:    time.Date(2025, 1, 2, 3, 4, 5, 0, time.UTC).Format(time.RFC3339),
	}
	b, err := json.Marshal(req)
	if err != nil {
		t.Fatalf("marshal error: %v", err)
	}
	s := string(b)
	if !containsAll(s, []string{"\"order_number_type\":1", "\"out_trade_no\":\"O202501010001\"", "\"logistics_type\":3", "\"delivery_mode\":1"}) {
		t.Fatalf("payload missing fields for out_trade_no: %s", s)
	}
}

func containsAll(s string, subs []string) bool {
	for _, sub := range subs {
		if !contains(s, sub) {
			return false
		}
	}
	return true
}

func containsAny(s string, subs []string) bool {
	for _, sub := range subs {
		if contains(s, sub) {
			return true
		}
	}
	return false
}

func contains(s, sub string) bool {
	return len(sub) == 0 || (len(s) >= len(sub) && indexOf(s, sub) >= 0)
}

func indexOf(s, sub string) int {
	for i := 0; i+len(sub) <= len(s); i++ {
		match := true
		for j := 0; j < len(sub); j++ {
			if s[i+j] != sub[j] {
				match = false
				break
			}
		}
		if match {
			return i
		}
	}
	return -1
}
