package cluster

import (
	"encoding/json"
	"testing"
	"time"

	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
	mgmtv1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	"google.golang.org/protobuf/types/known/timestamppb"

	"github.com/tidbcloud/devops/pkg/infra/utils/test"
)

func TestMigrationPrecheckAPI(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Migration Precheck API Suite", test.ReporterConfig())
}

var _ = Describe("DedicatedToPremiumPrecheck DTO", func() {
	It("converts the complete protobuf result", func() {
		createTime := time.Date(2026, time.August, 24, 1, 2, 3, 0, time.UTC)
		updateTime := createTime.Add(time.Minute)
		startTime := createTime.Add(2 * time.Minute)
		finishTime := createTime.Add(3 * time.Minute)
		precheck := &mgmtv1.DedicatedToPremiumPrecheck{
			Id:                     9007199254740993,
			SourceClusterId:        9007199254740994,
			MigrationAccountEmail:  "migration@pingcap.com",
			TargetPremiumProjectId: 9007199254740995,
			State:                  mgmtv1.DedicatedToPremiumPrecheckState_SUCCEEDED,
			FailureMessage:         "failure",
			CreateTime:             timestamppb.New(createTime),
			UpdateTime:             timestamppb.New(updateTime),
			StartTime:              timestamppb.New(startTime),
			FinishTime:             timestamppb.New(finishTime),
			Applicant:              "applicant@pingcap.com",
			Reports: []*mgmtv1.PrecheckReport{
				{
					Category: mgmtv1.PrecheckCategory_FEATURE_GAP,
					Summary: &mgmtv1.PrecheckSummary{
						TotalCount:       3,
						RiskFoundCount:   1,
						NoRiskFoundCount: 1,
						NeedsInputCount:  1,
					},
					Items: []*mgmtv1.PrecheckItem{
						{
							CheckKey: "feature",
							Title:    "Feature compatibility",
							Status:   mgmtv1.PrecheckItemStatus_RISK_FOUND,
							Why:      "unsupported",
							Evidence: "evidence",
							Action:   "remove feature",
						},
					},
					Complete:       true,
					ExecutionError: "execution error",
				},
			},
		}

		got := BuildDedicatedToPremiumPrecheck(precheck)

		Expect(got.ID).To(Equal("9007199254740993"))
		Expect(got.SourceClusterID).To(Equal("9007199254740994"))
		Expect(got.TargetPremiumProjectID).To(Equal("9007199254740995"))
		Expect(got.State).To(Equal("SUCCEEDED"))
		Expect(got.CreateTime).To(Equal(&createTime))
		Expect(got.UpdateTime).To(Equal(&updateTime))
		Expect(got.StartTime).To(Equal(&startTime))
		Expect(got.FinishTime).To(Equal(&finishTime))
		Expect(got.Reports).To(HaveLen(1))
		Expect(got.Reports[0].Category).To(Equal("FEATURE_GAP"))
		Expect(got.Reports[0].Summary).To(Equal(&DedicatedToPremiumPrecheckSummary{
			TotalCount:       3,
			RiskFoundCount:   1,
			NoRiskFoundCount: 1,
			NeedsInputCount:  1,
		}))
		Expect(got.Reports[0].Items).To(Equal([]*DedicatedToPremiumPrecheckItem{
			{
				CheckKey: "feature",
				Title:    "Feature compatibility",
				Status:   "RISK_FOUND",
				Why:      "unsupported",
				Evidence: "evidence",
				Action:   "remove feature",
			},
		}))
		Expect(got.Reports[0].Complete).To(BeTrue())
		Expect(got.Reports[0].ExecutionError).To(Equal("execution error"))

		encoded, err := json.Marshal(got)
		Expect(err).NotTo(HaveOccurred())
		var jsonResult map[string]any
		Expect(json.Unmarshal(encoded, &jsonResult)).To(Succeed())
		Expect(jsonResult["id"]).To(Equal("9007199254740993"))
		Expect(jsonResult["source_cluster_id"]).To(Equal("9007199254740994"))
		Expect(jsonResult["target_premium_project_id"]).To(Equal("9007199254740995"))
	})

	It("preserves nil timestamps and emits empty slices", func() {
		got := BuildDedicatedToPremiumPrecheck(&mgmtv1.DedicatedToPremiumPrecheck{})

		Expect(got.CreateTime).To(BeNil())
		Expect(got.UpdateTime).To(BeNil())
		Expect(got.StartTime).To(BeNil())
		Expect(got.FinishTime).To(BeNil())
		Expect(got.Reports).To(BeEmpty())
		Expect(got.Reports).NotTo(BeNil())

		items := BuildDedicatedToPremiumPrechecks(nil)
		Expect(items).To(BeEmpty())
		Expect(items).NotTo(BeNil())
	})
})
