package databi

import (
	"encoding/json"
	"testing"
)

func TestRollupByRegionGroupsCountriesAndRecomputesDerived(t *testing.T) {
	regions := []RegionInfo{
		{AppCode: "aslan", RegionID: 11, RegionCode: "MENA", RegionName: "中东", Countries: []string{"SA", "AE"}},
		{AppCode: "aslan", RegionID: 12, RegionCode: "SEA", RegionName: "东南亚", Countries: []string{"ID"}},
	}
	rows := []map[string]any{
		{"country_code": "SA", "recharge_usd_minor": int64(10000), "active_users": int64(100), "paid_users": int64(10), "recharge_users": int64(10), "gift_coin_spent": nil},
		{"country_code": "AE", "recharge_usd_minor": json.Number("5000"), "active_users": json.Number("50"), "paid_users": json.Number("5"), "recharge_users": json.Number("5"), "gift_coin_spent": nil},
		{"country_code": "ID", "recharge_usd_minor": int64(2000), "active_users": int64(40), "paid_users": int64(2), "recharge_users": int64(2), "gift_coin_spent": int64(700)},
		{"country_code": "XX", "recharge_usd_minor": int64(1), "active_users": int64(1), "paid_users": int64(0), "recharge_users": int64(0)},
	}
	out := rollupByRegion(rows, regionResolver(regions))
	if len(out) != 3 {
		t.Fatalf("expected 3 region rows (MENA/SEA/未划分), got %d", len(out))
	}
	mena := out[0]
	if got, _ := rowInt64(mena, "region_id"); got != 11 {
		t.Fatalf("expected first row to be region 11 by recharge desc, got %d", got)
	}
	if got, _ := rowInt64(mena, "recharge_usd_minor"); got != 15000 {
		t.Fatalf("expected MENA recharge 15000, got %d", got)
	}
	if got, _ := rowInt64(mena, "active_users"); got != 150 {
		t.Fatalf("expected MENA active users 150, got %d", got)
	}
	if got, ok := mena["arppu_usd_minor"].(int64); !ok || got != 1000 {
		t.Fatalf("expected MENA arppu 1000, got %v", mena["arppu_usd_minor"])
	}
	if mena["gift_coin_spent"] != nil {
		t.Fatalf("expected MENA gift_coin_spent nil when all rows nil, got %v", mena["gift_coin_spent"])
	}
	sea := out[1]
	if got, _ := rowInt64(sea, "gift_coin_spent"); got != 700 {
		t.Fatalf("expected SEA gift_coin_spent 700, got %d", got)
	}
	unassigned := out[2]
	if got, _ := rowInt64(unassigned, "region_id"); got != 0 {
		t.Fatalf("expected unassigned region id 0, got %d", got)
	}
}

func TestRollupByRegionPrefersRowRegionID(t *testing.T) {
	regions := []RegionInfo{{AppCode: "lalu", RegionID: 3, RegionCode: "LATAM", RegionName: "拉美", Countries: []string{"BR"}}}
	rows := []map[string]any{
		{"region_id": json.Number("3"), "country_id": int64(55), "recharge_usd_minor": int64(100)},
		{"region_id": int64(3), "country_id": int64(56), "recharge_usd_minor": int64(200)},
	}
	out := rollupByRegion(rows, regionResolver(regions))
	if len(out) != 1 {
		t.Fatalf("expected 1 region row, got %d", len(out))
	}
	if got := out[0]["region_name"]; got != "拉美" {
		t.Fatalf("expected region name 拉美, got %v", got)
	}
	if got, _ := rowInt64(out[0], "recharge_usd_minor"); got != 300 {
		t.Fatalf("expected recharge 300, got %d", got)
	}
}

func TestFilterRowsByRegion(t *testing.T) {
	regions := []RegionInfo{
		{AppCode: "yumi", RegionID: 21, Countries: []string{"SA"}},
		{AppCode: "yumi", RegionID: 22, Countries: []string{"EG"}},
	}
	rows := []map[string]any{
		{"country_code": "SA"},
		{"country_code": "EG"},
		{"country_code": "??"},
	}
	out := filterRowsByRegion(rows, regionResolver(regions), int64Set([]int64{21}))
	if len(out) != 1 || out[0]["country_code"] != "SA" {
		t.Fatalf("expected only SA row, got %v", out)
	}
}

func TestAllowedRegions(t *testing.T) {
	access := testAccess()
	if all, _ := allowedRegions(access, "lalu"); !all {
		t.Fatalf("expected whole-app access for lalu (region 0 scope)")
	}
	all, ids := allowedRegions(access, "aslan")
	if all || len(ids) != 2 {
		t.Fatalf("expected two region scopes for aslan, got all=%v ids=%v", all, ids)
	}
	if all, ids := allowedRegions(access, "yumi"); all || len(ids) != 0 {
		t.Fatalf("expected no access for yumi, got all=%v ids=%v", all, ids)
	}
}

func TestResolveKpiMonthClampsFuture(t *testing.T) {
	location := mustLocation(t, "Asia/Shanghai")
	month, start, end, err := resolveKpiMonth("2020-02", 0, location)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if month != "2020-02" {
		t.Fatalf("expected month 2020-02, got %s", month)
	}
	if start.Format("2006-01-02") != "2020-02-01" || end.Format("2006-01-02") != "2020-03-01" {
		t.Fatalf("unexpected month window %s ~ %s", start, end)
	}
	if _, _, _, err := resolveKpiMonth("2020/02", 0, location); err == nil {
		t.Fatalf("expected format error for 2020/02")
	}
}
