package listing

import (
	"encoding/json"
	"testing"
)

func TestConsumableValueOnlyCountsChargedResources(t *testing.T) {
	value := consumableValue(map[string]any{
		"resources": []any{
			map[string]any{"mode": "收费", "quantity": float64(5), "price": "0.1元/个"},
			map[string]any{"mode": "赠送", "quantity": float64(3), "price": "0.6元/个"},
			map[string]any{"mode": "收费", "quantity": float64(2), "price": "1元/2个"},
		},
	})

	if value != 1.5 {
		t.Fatalf("expected 1.5, got %.2f", value)
	}
}

func TestCalculateAdminAdjustedPriceByRatio(t *testing.T) {
	base, total, ratio := calculateAdminAdjustedPrice(AdminPriceAdjustRequest{BuyerRatio: 25}, 1000, 20)
	if base != 40 || total != 60 || ratio != 25 {
		t.Fatalf("unexpected adjusted price: base=%.2f total=%.2f ratio=%.2f", base, total, ratio)
	}
}

func TestCalculateAdminAdjustedPriceByTotalPrice(t *testing.T) {
	base, total, ratio := calculateAdminAdjustedPrice(AdminPriceAdjustRequest{BuyerTotalPrice: 70}, 1000, 20)
	if base != 50 || total != 70 || ratio != 20 {
		t.Fatalf("unexpected adjusted price: base=%.2f total=%.2f ratio=%.2f", base, total, ratio)
	}
}

func TestValidateRequestRequiresDepositAboveConsumables(t *testing.T) {
	req := CreateRequest{
		Title:          "测试账号",
		ServerRegion:   "烽火地带",
		Price:          100,
		DepositAmount:  2,
		HafCoinAmount:  1000000,
		ScreenshotURLS: []string{"https://example.com/a.png"},
		AssetSummary: map[string]any{
			"resources": []any{
				map[string]any{"mode": "收费", "quantity": float64(2), "price": "1元/个"},
			},
		},
	}

	if err := validateRequest(req, publishRules{}); err != ErrDepositTooLow {
		t.Fatalf("expected ErrDepositTooLow, got %v", err)
	}

	req.DepositAmount = 3
	if err := validateRequest(req, publishRules{}); err != nil {
		t.Fatalf("expected valid request, got %v", err)
	}
}

func TestApplySellerListingPriceUsesSellerTotalPrice(t *testing.T) {
	item := &ListingDTO{
		Price: 238,
		AssetSummary: map[string]any{
			"price_breakdown": map[string]any{
				"seller_total_price": 200,
			},
		},
	}

	applySellerListingPrice(item)

	if item.Price != 200 {
		t.Fatalf("expected seller price 200, got %.2f", item.Price)
	}
}

func TestApplySellerListingPriceKeepsFallbackPrice(t *testing.T) {
	item := &ListingDTO{
		Price: 238,
		AssetSummary: map[string]any{
			"price_breakdown": map[string]any{
				"seller_total_price": 0,
			},
		},
	}

	applySellerListingPrice(item)

	if item.Price != 238 {
		t.Fatalf("expected fallback price 238, got %.2f", item.Price)
	}
}

func TestParseExternalUploadItemsAcceptsSingleObject(t *testing.T) {
	items, err := parseExternalUploadItems(json.RawMessage(validExternalUploadDataJSON()))
	if err != nil {
		t.Fatalf("expected single upload parsed, got %v", err)
	}
	if len(items) != 1 || items[0].LoginMethod != "QQ账号密码" {
		t.Fatalf("unexpected items: %#v", items)
	}
}

func TestParseExternalUploadItemsReportsMissingFields(t *testing.T) {
	_, err := parseExternalUploadItems(json.RawMessage(`{"loginMethod":"QQ账号密码","currency":{"hafuCoin":197.1}}`))
	if err == nil {
		t.Fatal("expected validation error")
	}
	validationErr, ok := err.(UploadValidationError)
	if !ok {
		t.Fatalf("expected UploadValidationError, got %T", err)
	}
	expected := []string{"data.rank", "data.level", "data.currency.recycleRatio", "data.dailyConsumption"}
	for _, field := range expected {
		if !containsString(validationErr.Missing, field) {
			t.Fatalf("expected missing %s in %#v", field, validationErr.Missing)
		}
	}
}

func TestExternalAccountToCreateRequestMapsUploadFields(t *testing.T) {
	req := externalAccountToCreateRequest("客服1", 1772526103000, ExternalAccountData{
		LoginMethod:  "QQ账号密码",
		Rank:         "黑鹰",
		Level:        60,
		SafeSlots:    9,
		SecretKD:     1.6,
		DailyLossM:   7,
		Deposit:      400,
		BanRecord:    "无",
		CommonRegion: "郑州",
		Currency: ExternalUploadCurrency{
			HafuCoin:     197.1,
			RecycleRatio: 43,
			RecycleRent:  458,
		},
		DailyConsumption: ExternalDailyConsumption{Stamina: 7, Weight: 7},
		Inventory: ExternalUploadInventory{
			AWMBullets:    45,
			Level6Helmets: 14,
			Level6Armor:   17,
			Skins:         []string{"信条", "电锯惊魂"},
		},
	})

	if req.ServerRegion != "QQ" {
		t.Fatalf("expected QQ server region, got %q", req.ServerRegion)
	}
	if req.HafCoinAmount != 197100000 {
		t.Fatalf("expected haf coin amount 197100000, got %d", req.HafCoinAmount)
	}
	if req.Price != 458 || req.DepositAmount != 400 {
		t.Fatalf("unexpected price/deposit %.2f/%.2f", req.Price, req.DepositAmount)
	}
	if req.AssetSummary["season_insurance"] != "3*3" {
		t.Fatalf("expected 3*3 insurance, got %#v", req.AssetSummary["season_insurance"])
	}
	if req.AssetSummary["daily_loss_m"] != float64(7) {
		t.Fatalf("expected daily loss 7, got %#v", req.AssetSummary["daily_loss_m"])
	}
	if req.AssetSummary["stamina_level"] != "7级" || req.AssetSummary["load_level"] != "7级" {
		t.Fatalf("unexpected stamina/load: %#v", req.AssetSummary)
	}
	groups := req.AssetSummary["skin_groups"].(map[string][]string)
	if len(groups["melee"]) != 2 {
		t.Fatalf("expected melee skins mapped, got %#v", groups)
	}
	if len(req.ScreenshotURLS) != 1 || req.ScreenshotURLS[0] != defaultUploadScreenshot {
		t.Fatalf("expected default screenshot, got %#v", req.ScreenshotURLS)
	}
}

func validExternalUploadDataJSON() string {
	return `{
		"loginMethod":"QQ账号密码",
		"rank":"黑鹰",
		"level":60,
		"safeSlots":9,
		"secretKD":1.6,
		"dailyLossM":7,
		"deposit":400,
		"currency":{"hafuCoin":197.1,"recycleRatio":43,"recycleRent":458},
		"dailyConsumption":{"stamina":7,"weight":7}
	}`
}

func containsString(values []string, target string) bool {
	for _, value := range values {
		if value == target {
			return true
		}
	}
	return false
}
