package regionaction

import (
	"testing"
	"time"

	. "github.com/onsi/gomega"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	regionalv1 "github.com/tidbcloud/infra-provider/api/tidbcloud/regional-server/v1"

	opent "github.com/tidbcloud/devops/entity/operation"
)

func Test_upgradeAdminNodes_buildRequest(t *testing.T) {
	tests := []struct {
		name     string
		instance *opent.Instance
		info     *regionalv1.K8SInformation
		want     *regionalv1.CreateUpgradeOperationRequest
		wantErr  bool
	}{
		{
			name: "missing desired version",
			instance: &opent.Instance{
				ID:     123,
				Params: map[opent.ParamName]string{},
			},
			info: &regionalv1.K8SInformation{
				AppboxName: "test-appbox",
			},
			wantErr: true,
		},
		{
			name: "successful request with single admin node",
			instance: &opent.Instance{
				ID: 123,
				Params: map[opent.ParamName]string{
					opent.ParamDesiredVersion: "1.32",
				},
			},
			info: &regionalv1.K8SInformation{
				AppboxName: "test-appbox",
				AdminNodes: []*regionalv1.NodeGroup{{}, {}, {}}, // 3 admin nodes
			},
			want: &regionalv1.CreateUpgradeOperationRequest{
				UpgradeOperation: &regionalv1.UpgradeOperation{
					Name:       "devops-upgradeadminnodes-123",
					AppboxName: "test-appbox",
					Duration:   "15m",
					Ttl:        defaultTTL,
					Schedule:   time.Now().Add(1 * time.Minute).Format(cloudv1.UpgradeOperationScheduleLayout),
					Steps: []*regionalv1.UpgradeStep{
						{
							Target:  string(cloudv1.AdminNodes),
							Version: "1.32",
						},
					},
				},
			},
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			g := NewGomegaWithT(t)
			a := &upgradeAdminNodes{}
			got, err := a.buildRequest(tt.instance, tt.info)

			if tt.wantErr {
				g.Expect(err).To(HaveOccurred())
				g.Expect(got).To(BeNil())
				return
			}

			g.Expect(err).NotTo(HaveOccurred())
			// Compare everything except Schedule which is time-dependent
			if got != nil && tt.want != nil {
				gotOp := got.UpgradeOperation
				wantOp := tt.want.UpgradeOperation

				g.Expect(gotOp.Name).To(Equal(wantOp.Name))
				g.Expect(gotOp.AppboxName).To(Equal(wantOp.AppboxName))
				g.Expect(gotOp.Duration).To(Equal(wantOp.Duration))
				g.Expect(gotOp.Ttl).To(Equal(wantOp.Ttl))
				g.Expect(gotOp.Steps).To(Equal(wantOp.Steps))

				// Verify Schedule format and range
				schedule, err := time.Parse(cloudv1.UpgradeOperationScheduleLayout, gotOp.Schedule)
				g.Expect(err).NotTo(HaveOccurred())
				g.Expect(schedule.After(time.Now())).To(BeTrue())
				g.Expect(schedule.Before(time.Now().Add(2 * time.Minute))).To(BeTrue())
			}
		})
	}
}
