package cluster

import (
	"strconv"
	"time"

	"github.com/tidbcloud/devops/api"
	mgmtv1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	"google.golang.org/protobuf/types/known/timestamppb"
)

type ListDedicatedToPremiumPrechecksReq struct {
	api.PaginationReq `json:",inline"`
	SourceClusterID   string `form:"source_cluster_id" json:"source_cluster_id"`
}

type CreateDedicatedToPremiumPrecheckReq struct {
	SourceClusterID        string `json:"source_cluster_id" binding:"required"`
	MigrationAccountEmail  string `json:"migration_account_email"`
	TargetPremiumProjectID string `json:"target_premium_project_id"`
}

type ListDedicatedToPremiumPrechecksResp struct {
	api.BaseResp `json:",inline"`

	Items []*DedicatedToPremiumPrecheck `json:"items"`
	Total uint32                        `json:"total"`
}

type DedicatedToPremiumPrecheckResp struct {
	api.BaseResp `json:",inline"`

	Precheck *DedicatedToPremiumPrecheck `json:"precheck"`
}

type DedicatedToPremiumPrecheck struct {
	ID                     string                              `json:"id"`
	SourceClusterID        string                              `json:"source_cluster_id"`
	MigrationAccountEmail  string                              `json:"migration_account_email"`
	TargetPremiumProjectID string                              `json:"target_premium_project_id"`
	State                  string                              `json:"state"`
	Reports                []*DedicatedToPremiumPrecheckReport `json:"reports"`
	FailureMessage         string                              `json:"failure_message"`
	CreateTime             *time.Time                          `json:"create_time"`
	UpdateTime             *time.Time                          `json:"update_time"`
	FinishTime             *time.Time                          `json:"finish_time"`
	StartTime              *time.Time                          `json:"start_time"`
	Applicant              string                              `json:"applicant"`
}

type DedicatedToPremiumPrecheckReport struct {
	Category       string                             `json:"category"`
	Summary        *DedicatedToPremiumPrecheckSummary `json:"summary"`
	Items          []*DedicatedToPremiumPrecheckItem  `json:"items"`
	Complete       bool                               `json:"complete"`
	ExecutionError string                             `json:"execution_error"`
}

type DedicatedToPremiumPrecheckSummary struct {
	TotalCount       int32 `json:"total_count"`
	RiskFoundCount   int32 `json:"risk_found_count"`
	NoRiskFoundCount int32 `json:"no_risk_found_count"`
	NeedsInputCount  int32 `json:"needs_input_count"`
}

type DedicatedToPremiumPrecheckItem struct {
	CheckKey string `json:"check_key"`
	Title    string `json:"title"`
	Status   string `json:"status"`
	Why      string `json:"why"`
	Evidence string `json:"evidence"`
	Action   string `json:"action"`
}

func BuildDedicatedToPremiumPrechecks(prechecks []*mgmtv1.DedicatedToPremiumPrecheck) []*DedicatedToPremiumPrecheck {
	result := make([]*DedicatedToPremiumPrecheck, len(prechecks))
	for i, precheck := range prechecks {
		result[i] = BuildDedicatedToPremiumPrecheck(precheck)
	}
	return result
}

func BuildDedicatedToPremiumPrecheck(precheck *mgmtv1.DedicatedToPremiumPrecheck) *DedicatedToPremiumPrecheck {
	if precheck == nil {
		return nil
	}

	reports := make([]*DedicatedToPremiumPrecheckReport, len(precheck.GetReports()))
	for i, report := range precheck.GetReports() {
		reports[i] = buildDedicatedToPremiumPrecheckReport(report)
	}

	return &DedicatedToPremiumPrecheck{
		ID:                     strconv.FormatUint(precheck.GetId(), 10),
		SourceClusterID:        strconv.FormatUint(precheck.GetSourceClusterId(), 10),
		MigrationAccountEmail:  precheck.GetMigrationAccountEmail(),
		TargetPremiumProjectID: strconv.FormatUint(precheck.GetTargetPremiumProjectId(), 10),
		State:                  precheck.GetState().String(),
		Reports:                reports,
		FailureMessage:         precheck.GetFailureMessage(),
		CreateTime:             dedicatedToPremiumPrecheckTime(precheck.GetCreateTime()),
		UpdateTime:             dedicatedToPremiumPrecheckTime(precheck.GetUpdateTime()),
		FinishTime:             dedicatedToPremiumPrecheckTime(precheck.GetFinishTime()),
		StartTime:              dedicatedToPremiumPrecheckTime(precheck.GetStartTime()),
		Applicant:              precheck.GetApplicant(),
	}
}

func buildDedicatedToPremiumPrecheckReport(report *mgmtv1.PrecheckReport) *DedicatedToPremiumPrecheckReport {
	if report == nil {
		return nil
	}

	items := make([]*DedicatedToPremiumPrecheckItem, len(report.GetItems()))
	for i, item := range report.GetItems() {
		items[i] = buildDedicatedToPremiumPrecheckItem(item)
	}

	return &DedicatedToPremiumPrecheckReport{
		Category:       report.GetCategory().String(),
		Summary:        buildDedicatedToPremiumPrecheckSummary(report.GetSummary()),
		Items:          items,
		Complete:       report.GetComplete(),
		ExecutionError: report.GetExecutionError(),
	}
}

func buildDedicatedToPremiumPrecheckSummary(summary *mgmtv1.PrecheckSummary) *DedicatedToPremiumPrecheckSummary {
	if summary == nil {
		return nil
	}
	return &DedicatedToPremiumPrecheckSummary{
		TotalCount:       summary.GetTotalCount(),
		RiskFoundCount:   summary.GetRiskFoundCount(),
		NoRiskFoundCount: summary.GetNoRiskFoundCount(),
		NeedsInputCount:  summary.GetNeedsInputCount(),
	}
}

func buildDedicatedToPremiumPrecheckItem(item *mgmtv1.PrecheckItem) *DedicatedToPremiumPrecheckItem {
	if item == nil {
		return nil
	}
	return &DedicatedToPremiumPrecheckItem{
		CheckKey: item.GetCheckKey(),
		Title:    item.GetTitle(),
		Status:   item.GetStatus().String(),
		Why:      item.GetWhy(),
		Evidence: item.GetEvidence(),
		Action:   item.GetAction(),
	}
}

func dedicatedToPremiumPrecheckTime(timestamp *timestamppb.Timestamp) *time.Time {
	if timestamp == nil {
		return nil
	}
	t := timestamp.AsTime()
	return &t
}
