package payment

import (
	"context"
	"strings"
	"testing"

	"hyapp-admin-server/internal/model"
)

func TestFinanceCoinSellerRechargeOrderBillUsesBusinessTime(t *testing.T) {
	order := model.CoinSellerRechargeOrder{
		ID:             7,
		AppCode:        "lalu",
		TargetUserID:   10001,
		USDMinorAmount: 15000,
		CoinAmount:     12000000,
		ProviderCode:   "usdt",
		OrderDateMS:    1_783_708_200_000,
		CreatedAtMS:    1_783_881_000_000,
	}
	bill := financeCoinSellerRechargeOrderBill(order)
	if bill.CreatedAtMS != order.OrderDateMS || bill.PaidSyncedAtMS != order.OrderDateMS {
		t.Fatalf("finance bill must use selected business time: %+v", bill)
	}
	if bill.RechargeType != financeCoinSellerUSDTType {
		t.Fatalf("USDT admin order must expose the refined recharge source: %+v", bill)
	}
	order.ProviderCode = "mifapay"
	if mifapayBill := financeCoinSellerRechargeOrderBill(order); mifapayBill.RechargeType != financeCoinSellerMiFaPayType {
		t.Fatalf("MiFaPay admin order must expose the provider source: %+v", mifapayBill)
	}
	order.ProviderCode = "v5pay"
	if v5payBill := financeCoinSellerRechargeOrderBill(order); v5payBill.RechargeType != financeCoinSellerV5PayType {
		t.Fatalf("V5Pay admin order must expose the provider source: %+v", v5payBill)
	}
	order.ProviderCode = "unknown_legacy_provider"
	if legacyBill := financeCoinSellerRechargeOrderBill(order); legacyBill.RechargeType != financeCoinSellerThirdPartyType {
		t.Fatalf("unknown legacy provider must keep the aggregate third-party source: %+v", legacyBill)
	}
}

func TestFinanceCoinSellerRechargeSourceKeepsParentCompatibility(t *testing.T) {
	for _, rechargeType := range []string{"", financeCoinSellerRechargeType} {
		if source, ok := financeCoinSellerRechargeSource(rechargeType); !ok || source != "" {
			t.Fatalf("parent recharge type %q must include both sources: source=%q ok=%v", rechargeType, source, ok)
		}
	}
	if source, ok := financeCoinSellerRechargeSource(financeCoinSellerThirdPartyType); !ok || source != "third_party" {
		t.Fatalf("third-party source mismatch: source=%q ok=%v", source, ok)
	}
	if source, ok := financeCoinSellerRechargeSource(financeCoinSellerMiFaPayType); !ok || source != "mifapay" {
		t.Fatalf("MiFaPay source mismatch: source=%q ok=%v", source, ok)
	}
	if source, ok := financeCoinSellerRechargeSource(financeCoinSellerV5PayType); !ok || source != "v5pay" {
		t.Fatalf("V5Pay source mismatch: source=%q ok=%v", source, ok)
	}
	if source, ok := financeCoinSellerRechargeSource(financeCoinSellerUSDTType); !ok || source != "usdt" {
		t.Fatalf("USDT source mismatch: source=%q ok=%v", source, ok)
	}
}

func TestH5CoinSellerRechargeWhereScopesProviderBeforePagination(t *testing.T) {
	where, args := h5CoinSellerRechargeWhere("aslan", financeCoinSellerRechargeQuery{RechargeType: financeCoinSellerV5PayType})
	if !strings.Contains(where, "eo.provider_code = ?") || len(args) != 2 || args[1] != "v5pay" {
		t.Fatalf("V5Pay filter must be pushed into the indexed SQL query: where=%q args=%v", where, args)
	}
	where, args = h5CoinSellerRechargeWhere("aslan", financeCoinSellerRechargeQuery{RechargeType: financeCoinSellerThirdPartyType})
	if !strings.Contains(where, "eo.provider_code IN (?, ?)") || len(args) != 3 || args[1] != "mifapay" || args[2] != "v5pay" {
		t.Fatalf("third-party aggregate must contain both providers: where=%q args=%v", where, args)
	}
}

func TestNormalizeFinanceCoinSellerRegionIDRestoresRoundedLegacyID(t *testing.T) {
	handler := New(&mockPaymentWallet{}, nil, nil, nil, nil, WithMoneyRegionSources(&staticMoneyRegionSource{
		regions: []moneyRegionDTO{{AppCode: "aslan", RegionID: 2049040141349486594, RegionCode: "IN", Name: "印度"}},
	}))
	// 浏览器 JSON 把 2049040141349486594 圆整成 ...600；SQL 精确等值前必须先还原成目录精确值。
	if got := handler.normalizeFinanceCoinSellerRegionID(context.Background(), "aslan", 2049040141349486600); got != 2049040141349486594 {
		t.Fatalf("rounded legacy region id should normalize to catalog value, got %d", got)
	}
	// 目录没有的 ID 原样返回；2^53 以内的 hyapp 区域 ID 不查目录直接返回。
	if got := handler.normalizeFinanceCoinSellerRegionID(context.Background(), "aslan", 9_100_000_000_000_000_001); got != 9_100_000_000_000_000_001 {
		t.Fatalf("unknown region id should stay unchanged, got %d", got)
	}
	if got := handler.normalizeFinanceCoinSellerRegionID(context.Background(), "lalu", 10); got != 10 {
		t.Fatalf("small region id should stay unchanged, got %d", got)
	}
}
