package service

import (
	"testing"

	"github.com/tidbcloud/serverless-service/internal/domain/constant"
)

func TestSplitIntoTiers(t *testing.T) {
	defaultFree := constant.InstanceCapacityFreeLimit // 100

	tests := []struct {
		name       string
		totalCount int64
		want       map[constant.SkuType]int64
	}{
		{
			name:       "zero count",
			totalCount: 0,
			want:       nil,
		},
		{
			name:       "negative count",
			totalCount: -1,
			want:       nil,
		},
		{
			name:       "within free tier",
			totalCount: 50,
			want: map[constant.SkuType]int64{
				constant.SkuTypeInstanceCapacityFree: 50,
			},
		},
		{
			name:       "exactly at free tier limit",
			totalCount: 100,
			want: map[constant.SkuType]int64{
				constant.SkuTypeInstanceCapacityFree: 100,
			},
		},
		{
			name:       "one over free tier",
			totalCount: 101,
			want: map[constant.SkuType]int64{
				constant.SkuTypeInstanceCapacityFree:  100,
				constant.SkuTypeInstanceCapacityTier1: 1,
			},
		},
		{
			name:       "exactly at tier1 limit",
			totalCount: 5000,
			want: map[constant.SkuType]int64{
				constant.SkuTypeInstanceCapacityFree:  100,
				constant.SkuTypeInstanceCapacityTier1: 4900,
			},
		},
		{
			name:       "one over tier1",
			totalCount: 5001,
			want: map[constant.SkuType]int64{
				constant.SkuTypeInstanceCapacityFree:  100,
				constant.SkuTypeInstanceCapacityTier1: 4900,
				constant.SkuTypeInstanceCapacityTier2: 1,
			},
		},
		{
			name:       "exactly at tier2 limit",
			totalCount: 100000,
			want: map[constant.SkuType]int64{
				constant.SkuTypeInstanceCapacityFree:  100,
				constant.SkuTypeInstanceCapacityTier1: 4900,
				constant.SkuTypeInstanceCapacityTier2: 95000,
			},
		},
		{
			name:       "spec example: 600000",
			totalCount: 600000,
			want: map[constant.SkuType]int64{
				constant.SkuTypeInstanceCapacityFree:  100,
				constant.SkuTypeInstanceCapacityTier1: 4900,
				constant.SkuTypeInstanceCapacityTier2: 95000,
				constant.SkuTypeInstanceCapacityTier3: 400000,
				constant.SkuTypeInstanceCapacityTier4: 100000,
			},
		},
		{
			name:       "exactly at tier3 limit",
			totalCount: 500000,
			want: map[constant.SkuType]int64{
				constant.SkuTypeInstanceCapacityFree:  100,
				constant.SkuTypeInstanceCapacityTier1: 4900,
				constant.SkuTypeInstanceCapacityTier2: 95000,
				constant.SkuTypeInstanceCapacityTier3: 400000,
			},
		},
		{
			name:       "large count in tier4",
			totalCount: 1500000,
			want: map[constant.SkuType]int64{
				constant.SkuTypeInstanceCapacityFree:  100,
				constant.SkuTypeInstanceCapacityTier1: 4900,
				constant.SkuTypeInstanceCapacityTier2: 95000,
				constant.SkuTypeInstanceCapacityTier3: 400000,
				constant.SkuTypeInstanceCapacityTier4: 1000000,
			},
		},
		{
			name:       "single instance",
			totalCount: 1,
			want: map[constant.SkuType]int64{
				constant.SkuTypeInstanceCapacityFree: 1,
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			got := SplitIntoTiers(tt.totalCount, defaultFree)
			if len(got) != len(tt.want) {
				t.Errorf(
					"SplitIntoTiers(%d, %d) returned %d tiers, want %d",
					tt.totalCount, defaultFree, len(got), len(tt.want),
				)
				t.Logf("got:  %v", got)
				t.Logf("want: %v", tt.want)
				return
			}
			for k, wantV := range tt.want {
				gotV, ok := got[k]
				if !ok {
					t.Errorf("SplitIntoTiers(%d, %d) missing tier %v", tt.totalCount, defaultFree, k)
					return
				}
				if gotV != wantV {
					t.Errorf("SplitIntoTiers(%d, %d) tier %v = %d, want %d", tt.totalCount, defaultFree, k, gotV, wantV)
				}
			}
		})
	}
}

func TestSplitIntoTiers_CustomFreeTier(t *testing.T) {
	// Org with FreeTierOverride = 200: first 200 instances are free,
	// then tier1 starts at 201 and retains the same bracket size (4900).
	t.Run("custom free tier 200", func(t *testing.T) {
		got := SplitIntoTiers(250, 200)
		want := map[constant.SkuType]int64{
			constant.SkuTypeInstanceCapacityFree:  200,
			constant.SkuTypeInstanceCapacityTier1: 50,
		}
		if len(got) != len(want) {
			t.Fatalf("got %d tiers, want %d: %v", len(got), len(want), got)
		}
		for k, w := range want {
			if got[k] != w {
				t.Errorf("tier %v = %d, want %d", k, got[k], w)
			}
		}
	})

	// Custom free tier = 0 means no free tier, everything starts from tier1.
	t.Run("custom free tier 0 falls back to default", func(t *testing.T) {
		got := SplitIntoTiers(150, 0)
		if got[constant.SkuTypeInstanceCapacityFree] != 100 {
			t.Errorf("free tier = %d, want 100 (default)", got[constant.SkuTypeInstanceCapacityFree])
		}
		if got[constant.SkuTypeInstanceCapacityTier1] != 50 {
			t.Errorf("tier1 = %d, want 50", got[constant.SkuTypeInstanceCapacityTier1])
		}
	})

	// Custom free tier larger than total — everything is free.
	t.Run("custom free tier exceeds total", func(t *testing.T) {
		got := SplitIntoTiers(50, 200)
		if len(got) != 1 {
			t.Fatalf("expected 1 tier, got %d: %v", len(got), got)
		}
		if got[constant.SkuTypeInstanceCapacityFree] != 50 {
			t.Errorf("free = %d, want 50", got[constant.SkuTypeInstanceCapacityFree])
		}
	})
}
