package service

import (
	"testing"
	"time"

	"oci-portal/internal/oci"
)

func TestAlignDown(t *testing.T) {
	tests := []struct {
		name        string
		in          time.Time
		granularity string
		want        time.Time
	}{
		{
			name:        "daily 截到当天零点",
			in:          time.Date(2026, 7, 3, 15, 4, 5, 0, time.UTC),
			granularity: "DAILY",
			want:        time.Date(2026, 7, 3, 0, 0, 0, 0, time.UTC),
		},
		{
			name:        "daily 已在边界不变",
			in:          time.Date(2026, 7, 3, 0, 0, 0, 0, time.UTC),
			granularity: "DAILY",
			want:        time.Date(2026, 7, 3, 0, 0, 0, 0, time.UTC),
		},
		{
			name:        "monthly 截到当月一号",
			in:          time.Date(2026, 7, 15, 8, 0, 0, 0, time.UTC),
			granularity: "MONTHLY",
			want:        time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC),
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := alignDown(tt.in, tt.granularity); !got.Equal(tt.want) {
				t.Errorf("alignDown() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestAlignUp(t *testing.T) {
	tests := []struct {
		name        string
		in          time.Time
		granularity string
		want        time.Time
	}{
		{
			name:        "daily 进到明日零点覆盖当天",
			in:          time.Date(2026, 7, 3, 15, 4, 5, 0, time.UTC),
			granularity: "DAILY",
			want:        time.Date(2026, 7, 4, 0, 0, 0, 0, time.UTC),
		},
		{
			name:        "daily 已在边界不进位",
			in:          time.Date(2026, 7, 3, 0, 0, 0, 0, time.UTC),
			granularity: "DAILY",
			want:        time.Date(2026, 7, 3, 0, 0, 0, 0, time.UTC),
		},
		{
			name:        "monthly 进到下月一号覆盖当月",
			in:          time.Date(2026, 7, 15, 8, 0, 0, 0, time.UTC),
			granularity: "MONTHLY",
			want:        time.Date(2026, 8, 1, 0, 0, 0, 0, time.UTC),
		},
		{
			name:        "monthly 十二月进位跨年",
			in:          time.Date(2026, 12, 20, 0, 0, 0, 0, time.UTC),
			granularity: "MONTHLY",
			want:        time.Date(2027, 1, 1, 0, 0, 0, 0, time.UTC),
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := alignUp(tt.in, tt.granularity); !got.Equal(tt.want) {
				t.Errorf("alignUp() = %v, want %v", got, tt.want)
			}
		})
	}
}

func TestApplyCostDefaults(t *testing.T) {
	var q oci.CostQuery
	applyCostDefaults(&q)
	if q.Granularity != "DAILY" || q.QueryType != "COST" || q.GroupBy != "service" {
		t.Errorf("defaults = %s/%s/%s, want DAILY/COST/service", q.Granularity, q.QueryType, q.GroupBy)
	}
	if q.StartTime.IsZero() || q.EndTime.IsZero() {
		t.Fatal("time window not defaulted")
	}
	window := q.EndTime.Sub(q.StartTime)
	if window < 30*24*time.Hour || window > 32*24*time.Hour {
		t.Errorf("default window = %v, want ~30d", window)
	}
	if !q.EndTime.After(time.Now().UTC()) {
		t.Errorf("endTime %v should be aligned up past now (open interval)", q.EndTime)
	}
}

func TestValidateEmails(t *testing.T) {
	tests := []struct {
		name    string
		emails  []string
		wantErr bool
	}{
		{name: "空列表合法表示关闭 test mode", emails: nil, wantErr: false},
		{name: "正常邮箱", emails: []string{"a@b.com", "c@d.org"}, wantErr: false},
		{name: "缺少@", emails: []string{"not-an-email"}, wantErr: true},
		{name: "含空格", emails: []string{"a b@c.com"}, wantErr: true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := validateEmails(tt.emails); (err != nil) != tt.wantErr {
				t.Errorf("validateEmails(%v) error = %v, wantErr %v", tt.emails, err, tt.wantErr)
			}
		})
	}
}
