package main

import (
	"fmt"
	"log"
	"strings"
	"time"
	"user-behavior/pkg/clinic_event"
	"user-behavior/pkg/db"
	"user-behavior/pkg/feishu"
	"user-behavior/pkg/model"

	"github.com/spf13/viper"
)

var lastTimestamp time.Time

var creatingClusters map[uint64]bool
var creatingScalings map[uint64]bool
var lastFetchPOCTenants map[uint64]bool

func main() {
	// Do startup settings
	viper.Set("scope", "prod")
	viper.SetConfigName("conf")     // name of config file (without extension)
	viper.SetConfigType("yaml")     // REQUIRED if the config file does not have the extension in the name
	viper.AddConfigPath("./config") // optionally look for config in the working directory
	err := viper.ReadInConfig()     // Find and read the config file
	log.Println(viper.GetString("jira_token.tcoc_token"))
	if err != nil { // Handle errors reading the config file
		panic(fmt.Errorf("Fatal error config file: %w \n", err))
	}

	// init clinic event
	clinic_event.InitEventClient()
	//runScheduledMonitor()
	refactoredMain()
}

func runScheduledMonitor() {
	for {
		ts, err := db.GetNewestTimestamp()
		if err != nil {
			feishu.SendMessageToInternalReportChat("fetch first timestamp error, retrying...")
			time.Sleep(10 * time.Second)
		} else {
			lastTimestamp = ts.Add(-time.Second)
			break
		}
	}
	//lastTimestamp = time.Date(2022, time.June, 1, 0, 0, 0, 0, time.UTC)
	creatingClusters = make(map[uint64]bool)
	creatingScalings = make(map[uint64]bool)
	firstTime := false
	for {
		var newestTimestamp time.Time
		for {
			ts, err := db.GetNewestTimestamp()
			if err != nil {
				feishu.SendMessageToInternalReportChat("fetch timestamp")
			}
			if err != nil {
				feishu.SendMessageToInternalReportChat("fetch new timestamp error, retrying...")
				time.Sleep(10 * time.Second)
			} else {
				newestTimestamp = ts
				break
			}
		}
		if newestTimestamp != lastTimestamp {
			ondemandReportText, ondemandErr := generateTextForPOCOrOndemand(model.Params{PlanType: "on_demand", LastTimestamp: lastTimestamp, CurrentTimestamp: newestTimestamp})
			pocReportText, pocErr := generateTextForPOCOrOndemand(model.Params{PlanType: "poc", LastTimestamp: lastTimestamp, CurrentTimestamp: newestTimestamp})

			/*if lastTimestamp.Day() != newestTimestamp.Day() {
				reports := generateDailyReportsForDevTier()
				for region, text := range reports {
					feishu.SendMessageToInternalReportChat(region + text)
				}
			}*/
			// TODO: do someting for doc updater
			if pocErr == nil && ondemandErr == nil {
				if pocReportText != "" {
					if firstTime {
						feishu.SendCardToInternalReportChat(model.FeishuCardParams{Text: pocReportText, Title: "POC User Behavior", Color: "orange"})
					} else {
						feishu.SendCardToMonitorChat(model.FeishuCardParams{Text: pocReportText, Title: "POC User Behavior", Color: "orange"})
					}
				}
				if ondemandReportText != "" {
					if firstTime {
						feishu.SendCardToInternalReportChat(model.FeishuCardParams{Text: ondemandReportText, Title: "On-demand User Behavior", Color: "blue"})
					} else {
						feishu.SendCardToMonitorChat(model.FeishuCardParams{Text: ondemandReportText, Title: "On-demand User Behavior", Color: "blue"})
					}
				}
				lastTimestamp = newestTimestamp
			} else {
				feishu.SendMessageToInternalReportChat("fetch error at timestamp " + newestTimestamp.String())
			}
		}
		time.Sleep(5 * time.Minute)
	}

}

func generateTextForPOCOrOndemand(params model.Params) (string, error) {
	activeTenants, err := db.GetActiveUsers(params)
	if err != nil {
		return "", err
	}
	activeTenantMap := make(map[uint64]model.Tenant)
	for _, tenant := range activeTenants {
		activeTenantMap[tenant.Id] = tenant
	}
	activeClusters, err := db.GetAllClusters(params)
	if err != nil {
		return "", err
	}
	activeClusterMap := make(map[uint64]model.Cluster)
	for _, cluster := range activeClusters {
		if cluster.Status != "cleared" && cluster.Status != "deleted" && cluster.Status != "deletecomplete" && cluster.Status != "unknown" {
			activeClusterMap[cluster.Id] = cluster
		}
	}

	messageText := ""

	// Backups
	backupText := ""
	startedBackups, err := db.GetNewStartBackups(params)
	if err != nil {
		return "", err
	}
	count := 0
	for _, backup := range startedBackups {
		tenant, exist := activeTenantMap[backup.TenantId]
		if exist && tenant.Plan == params.PlanType {
			if _, exist = activeClusterMap[backup.ClusterId]; exist {
				if activeTenantMap[backup.TenantId].Alias != "" {
					backup.TenantName = activeTenantMap[backup.TenantId].Alias
				}
				backupText = backupText + fmt.Sprintf("**[%s]**The %s backup(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) **started**.\n", backup.Region, backup.BsType, backup.Id, backup.Status, backup.ClusterId, backup.TenantName, backup.TenantId)
				if backup.Status == "failed" && backup.Message != "" {
					backupText += ("**Error Message:** " + backup.Message + "\n")
				}
				count++
			}
		}
	}
	if count != 0 {
		backupText += "\n"
	}
	finishedBackups, err := db.GetNewFinishedBackups(params)
	if err != nil {
		return "", err
	}
	count = 0
	for _, backup := range finishedBackups {
		tenant, exist := activeTenantMap[backup.TenantId]
		if exist && tenant.Plan == params.PlanType {
			if _, exist = activeClusterMap[backup.ClusterId]; exist {
				if activeTenantMap[backup.TenantId].Alias != "" {
					backup.TenantName = activeTenantMap[backup.TenantId].Alias
				}
				backupText = backupText + fmt.Sprintf("**[%s]**The %s backup(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) **finished**.\n", backup.Region, backup.BsType, backup.Id, backup.Status, backup.ClusterId, backup.TenantName, backup.TenantId)
				if backup.Status == "failed" && backup.Message != "" {
					backupText += ("**Error Message:** " + backup.Message + "\n")
				}
				count++
			}
		}
	}
	if count != 0 {
		backupText += "\n"
	}
	longLastBackups, err := db.GetLastTooLongBackups(params)
	if err != nil {
		return "", err
	}
	count = 0
	for _, backup := range longLastBackups {
		tenant, exist := activeTenantMap[backup.TenantId]
		if exist && tenant.Plan == params.PlanType {
			if _, exist = activeClusterMap[backup.ClusterId]; exist {
				if activeTenantMap[backup.TenantId].Alias != "" {
					backup.TenantName = activeTenantMap[backup.TenantId].Alias
				}
				backupText = backupText + fmt.Sprintf("**[%s]**The %s backup(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) lasts more than **3** hours, please take a look.\n", backup.Region, backup.BsType, backup.Id, backup.Status, backup.ClusterId, backup.TenantName, backup.TenantId)
				if backup.Status == "failed" && backup.Message != "" {
					backupText += ("**Error Message:** " + backup.Message + "\n")
				}
				count++
			}
		}
	}
	if count != 0 {
		backupText += "\n"
	}
	if backupText != "" {
		backupText = "**Backups:**\n" + backupText
	}
	messageText += backupText

	// Restores
	restoreText := ""
	startedRestores, err := db.GetNewStartRestores(params)
	if err != nil {
		return "", err
	}
	count = 0
	for _, restore := range startedRestores {
		tenant, exist := activeTenantMap[restore.TenantId]
		if exist && tenant.Plan == params.PlanType {
			if _, exist = activeClusterMap[restore.ClusterId]; exist {
				if activeTenantMap[restore.TenantId].Alias != "" {
					restore.TenantName = activeTenantMap[restore.TenantId].Alias
				}
				restoreText = restoreText + fmt.Sprintf("**[%s]**The restore(%d)[status: **%s**] of cluster(%d) of tenant**[%s]**(%d) **started**.\n", restore.Region, restore.Id, restore.Status, restore.ClusterId, restore.TenantName, restore.TenantId)
				if restore.Status == "failed" && restore.Message != "" {
					restoreText += ("**Error Message:** " + restore.Message + "\n")
				}
				count++
			}
		}
	}
	if count != 0 {
		restoreText += "\n"
	}
	finishedRestores, err := db.GetNewFinishedRestores(params)
	if err != nil {
		return "", err
	}
	count = 0
	for _, restore := range finishedRestores {
		tenant, exist := activeTenantMap[restore.TenantId]
		if exist && tenant.Plan == params.PlanType {
			if _, exist = activeClusterMap[restore.ClusterId]; exist {
				if activeTenantMap[restore.TenantId].Alias != "" {
					restore.TenantName = activeTenantMap[restore.TenantId].Alias
				}
				restoreText = restoreText + fmt.Sprintf("**[%s]**The restore(%d)[status: **%s**] of cluster(%d) of tenant**[%s]**(%d) **finished**.\n", restore.Region, restore.Id, restore.Status, restore.ClusterId, restore.TenantName, restore.TenantId)
				if restore.Status == "failed" && restore.Message != "" {
					restoreText += ("**Error Message:** " + restore.Message + "\n")
				}
				count++
			}
		}
	}
	if count != 0 {
		restoreText += "\n"
	}
	longLastRestores, err := db.GetLastTooLongRestores(params)
	if err != nil {
		return "", err
	}
	count = 0
	for _, restore := range longLastRestores {
		tenant, exist := activeTenantMap[restore.TenantId]
		if exist && tenant.Plan == params.PlanType {
			if _, exist = activeClusterMap[restore.ClusterId]; exist {
				if activeTenantMap[restore.TenantId].Alias != "" {
					restore.TenantName = activeTenantMap[restore.TenantId].Alias
				}
				restoreText = restoreText + fmt.Sprintf("**[%s]**The restore(%d)[status: **%s**] of cluster(%d) of tenant**[%s]**(%d) lasts more than **3** hours, please take a look.\n", restore.Region, restore.Id, restore.Status, restore.ClusterId, restore.TenantName, restore.TenantId)
				if restore.Status == "failed" && restore.Message != "" {
					restoreText += ("**Error Message:** " + restore.Message + "\n")
				}
				count++
			}
		}
	}
	if count != 0 {
		restoreText += "\n"
	}
	if restoreText != "" {
		restoreText = "**Restores:**\n" + restoreText
		if messageText != "" {
			restoreText = "\n --------------\n" + restoreText
		}
	}
	messageText += restoreText

	// Imports
	importText := ""
	startedImports, err := db.GetNewStartImports(params)
	if err != nil {
		return "", err
	}
	count = 0
	for _, oneImport := range startedImports {
		tenant, exist := activeTenantMap[oneImport.TenantId]
		if exist && tenant.Plan == params.PlanType {
			if _, exist = activeClusterMap[oneImport.ClusterId]; exist {
				if activeTenantMap[oneImport.TenantId].Alias != "" {
					oneImport.TenantName = activeTenantMap[oneImport.TenantId].Alias
				}
				importText = importText + fmt.Sprintf("**[%s]**The import(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) **started**.\n", oneImport.Region, oneImport.Id, oneImport.Status, oneImport.ClusterId, oneImport.TenantName, oneImport.TenantId)
				if oneImport.Status == "failed" && oneImport.Message != "" {
					importText += ("**Error Message:** " + oneImport.Message + "\n")
				}
				count++
			}
		}
	}
	if count != 0 {
		importText += "\n"
	}
	finishedImports, err := db.GetNewFinishedImports(params)
	if err != nil {
		return "", err
	}
	count = 0
	for _, oneImport := range finishedImports {
		tenant, exist := activeTenantMap[oneImport.TenantId]
		if exist && tenant.Plan == params.PlanType {
			if _, exist = activeClusterMap[oneImport.ClusterId]; exist {
				if activeTenantMap[oneImport.TenantId].Alias != "" {
					oneImport.TenantName = activeTenantMap[oneImport.TenantId].Alias
				}
				importText = importText + fmt.Sprintf("**[%s]**The import(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) **finished**.\n", oneImport.Region, oneImport.Id, oneImport.Status, oneImport.ClusterId, oneImport.TenantName, oneImport.TenantId)
				if oneImport.Status == "failed" && oneImport.Message != "" {
					importText += ("**Error Message:** " + oneImport.Message + "\n")
				}
				count++
			}
		}
	}
	if count != 0 {
		importText += "\n"
	}
	longLastImports, err := db.GetLastTooLongImports(params)
	if err != nil {
		return "", err
	}
	count = 0
	for _, oneImport := range longLastImports {
		tenant, exist := activeTenantMap[oneImport.TenantId]
		if exist && tenant.Plan == params.PlanType {
			if _, exist = activeClusterMap[oneImport.ClusterId]; exist {
				if activeTenantMap[oneImport.TenantId].Alias != "" {
					oneImport.TenantName = activeTenantMap[oneImport.TenantId].Alias
				}
				importText = importText + fmt.Sprintf("**[%s]**The import(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) lasts more than **3** hours, please take a look.\n", oneImport.Region, oneImport.Id, oneImport.Status, oneImport.ClusterId, oneImport.TenantName, oneImport.TenantId)
				if oneImport.Status == "failed" && oneImport.Message != "" {
					importText += ("**Error Message:** " + oneImport.Message + "\n")
				}
				count++
			}
		}
	}
	if count != 0 {
		importText += "\n"
	}
	if importText != "" {
		importText = "**Imports:**\n" + importText
		if messageText != "" {
			importText = "\n --------------\n" + importText
		}
	}
	messageText += importText

	// New Tenants
	if params.PlanType == "poc" {
		newTenantText := ""
		tenants, err := db.GetNewUsers(params)
		if err != nil {
			return "", err
		}
		for _, tenant := range tenants {
			tenant.Name = tenant.Alias
			if tenant.Plan == params.PlanType {
				newTenantText = newTenantText + fmt.Sprintf("**[%s]**New tenant **[%s]**(%d)\n", tenant.Region, tenant.Name, tenant.Id)
			}
		}
		if newTenantText != "" {
			newTenantText = "**New Tenants:**\n" + newTenantText
			if messageText != "" {
				newTenantText = "\n --------------\n" + newTenantText
			}
		}
		messageText += newTenantText
	} else if params.PlanType == "on_demand" {
		newOndemandText := ""
		tenants, err := db.GetNewUsers(params)
		if err != nil {
			return "", err
		}
		for _, tenant := range tenants {
			tenant.Name = tenant.Alias
			if tenant.Plan == params.PlanType {
				if tenant.ThirdPartyAccountProvider != "" {
					newOndemandText = newOndemandText + fmt.Sprintf("**[%s]**Newly on-demand **[%s]**(%d) from %s\n", tenant.Region, tenant.Name, tenant.Id, tenant.ThirdPartyAccountProvider)
				} else if lastFetchPOCTenants != nil && lastFetchPOCTenants[tenant.Id] == true {
					newOndemandText = newOndemandText + fmt.Sprintf("**[%s]**Newly on-demand **[%s]**(%d) from POC\n", tenant.Region, tenant.Name, tenant.Id)
				} else {
					newOndemandText = newOndemandText + fmt.Sprintf("**[%s]**Newly on-demand **[%s]**(%d)\n", tenant.Region, tenant.Name, tenant.Id)
				}
			}
		}
		if newOndemandText != "" {
			newOndemandText = "**New On-demands:**\n" + newOndemandText
			if messageText != "" {
				newOndemandText = "\n --------------\n" + newOndemandText
			}
		}
		messageText += newOndemandText
	}

	// Cluster Creation
	creationText := ""
	for _, cluster := range activeClusters {
		if (cluster.CreatedAt.After(params.LastTimestamp) || cluster.CreatedAt.Equal(params.LastTimestamp)) && cluster.CreatedAt.Before(params.CurrentTimestamp) && activeTenantMap[cluster.TenantId].Plan == params.PlanType {
			if activeTenantMap[cluster.TenantId].Alias != "" {
				cluster.TenantName = activeTenantMap[cluster.TenantId].Alias
			}
			creationText = creationText + fmt.Sprintf("**[%s]**The creation of cluster(%d)[status: **%s**] of tenant[%s]-(%d) **started**.\n", cluster.Region, cluster.Id, cluster.Status, cluster.TenantName, cluster.TenantId)
			creatingClusters[cluster.Id] = true
			count++
		}
	}
	if count > 0 {
		creationText += "\n"
	}
	for id := range creatingClusters {
		if _, exist := activeClusterMap[id]; exist {
			if creatingClusters[id] == true && activeClusterMap[id].Status != "created" && activeClusterMap[id].Status != "initializing" && activeClusterMap[id].Status != "preparing" && activeClusterMap[id].Status != "launching" && activeTenantMap[activeClusterMap[id].TenantId].Plan == params.PlanType {
				cluster := activeClusterMap[id]
				if activeTenantMap[cluster.TenantId].Alias != "" {
					cluster.TenantName = activeTenantMap[cluster.TenantId].Alias
				}
				creationText = creationText + fmt.Sprintf("**[%s]**The creation of cluster(%d)[status: **%s**] of tenant[%s]-(%d) **finished**.\n", cluster.Region, cluster.Id, cluster.Status, cluster.TenantName, cluster.TenantId)
				creatingClusters[cluster.Id] = false
				count++
			}
		}
	}
	if count > 0 {
		creationText += "\n"
	}
	for _, cluster := range activeClusters {
		if (cluster.Status == "created" || cluster.Status == "initializing" || cluster.Status == "preparing" || cluster.Status == "launching") && cluster.CreatedAt.Before(params.CurrentTimestamp.Add(-time.Hour)) && activeTenantMap[cluster.TenantId].Plan == params.PlanType {
			if activeTenantMap[cluster.TenantId].Alias != "" {
				cluster.TenantName = activeTenantMap[cluster.TenantId].Alias
			}
			creationText = creationText + fmt.Sprintf("**[%s]**The creation of cluster(%d)[status: **%s**] of tenant[%s]-(%d) last more than **1 hour**, please take a look.\n", cluster.Region, cluster.Id, cluster.Status, cluster.TenantName, cluster.TenantId)
			creatingClusters[cluster.Id] = true
			count++
		}
	}
	if count > 0 {
		creationText += "\n"
	}
	if creationText != "" {
		creationText = "**Cluster creations:**\n" + creationText
		if messageText != "" {
			creationText = "\n --------------\n" + creationText
		}
	}
	messageText += creationText

	// Cluster Scalings
	scalingText := ""
	startedScalings, err := db.GetClusterScalingStarts(params)
	if err != nil {
		return "", err
	}
	count = 0
	for _, scaling := range startedScalings {
		tenant, exist := activeTenantMap[scaling.TenantId]
		if scaling.Type == "scale" && tenant.Plan == params.PlanType {
			if _, exist = activeClusterMap[scaling.ClusterId]; exist {
				if activeTenantMap[scaling.TenantId].Alias != "" {
					scaling.TenantName = activeTenantMap[scaling.TenantId].Alias
				}
				scalingText = scalingText + fmt.Sprintf("**[%s]**The scaling(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) **started**.\n", scaling.Region, scaling.Id, scaling.Status, scaling.ClusterId, scaling.TenantName, scaling.TenantId)
				if scaling.Status == "failed" && scaling.Message != "" {
					scalingText += ("**Error Message:** " + scaling.Message + "\n")
				}
				count++
			}
		}
	}
	if count > 0 {
		scalingText += "\n"
	}
	finishedScalings, err := db.GetClusterScalingFinishes(params)
	if err != nil {
		return "", err
	}
	for _, scaling := range finishedScalings {
		tenant, exist := activeTenantMap[scaling.TenantId]
		if scaling.Type == "scale" && exist && tenant.Plan == params.PlanType {
			if activeTenantMap[scaling.TenantId].Alias != "" {
				scaling.TenantName = activeTenantMap[scaling.TenantId].Alias
			}
			scalingText = scalingText + fmt.Sprintf("**[%s]**The scaling(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) **finished**.\n", scaling.Region, scaling.Id, scaling.Status, scaling.ClusterId, scaling.TenantName, scaling.TenantId)
			if scaling.Status == "failed" && scaling.Message != "" {
				scalingText += ("**Error Message:** " + scaling.Message + "\n")
			}
			count++
		}
	}
	if count > 0 {
		scalingText += "\n"
	}
	longLastScalings, err := db.GetClusterScalingLastsTooLong(params)
	if err != nil {
		return "", err
	}
	count = 0
	for _, scaling := range longLastScalings {
		tenant, exist := activeTenantMap[scaling.TenantId]
		if scaling.Type == "scale" && exist && tenant.Plan == params.PlanType {
			cluster, exist := activeClusterMap[scaling.ClusterId]
			fStatusIn := func(c model.Cluster) bool {
				statu := []string{"cleared", "deleted", "deletecomplete", "unknown", "normal", "created", "done"}
				ret := false
				for _, status := range statu {
					if c.Status == status {
						ret = true
					}
				}
				return ret
			}
			if exist && !fStatusIn(cluster) && scaling.Status != "done" {
				if activeTenantMap[scaling.TenantId].Alias != "" {
					scaling.TenantName = activeTenantMap[scaling.TenantId].Alias
				}
				scalingText = scalingText + fmt.Sprintf("**[%s]**The scaling(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) lasts more than **3** hours, please take a look.\n", scaling.Region, scaling.Id, scaling.Status, scaling.ClusterId, scaling.TenantName, scaling.TenantId)
				if scaling.Status == "failed" && scaling.Message != "" {
					scalingText += ("**Error Message:** " + scaling.Message + "\n")
				}
				count++
			}
		}
	}
	if scalingText != "" {
		scalingText = "**Scalings:**\n" + scalingText
		if messageText != "" {
			scalingText = "\n --------------\n" + scalingText
		}
	}
	messageText += scalingText

	// Cluster Pausing
	pauseText := ""
	if err != nil {
		return "", err
	}
	count = 0
	for _, scaling := range startedScalings {
		tenant, exist := activeTenantMap[scaling.TenantId]
		if scaling.Type == "pause" && tenant.Plan == params.PlanType {
			if _, exist = activeClusterMap[scaling.ClusterId]; exist {
				if activeTenantMap[scaling.TenantId].Alias != "" {
					scaling.TenantName = activeTenantMap[scaling.TenantId].Alias
				}
				pauseText = pauseText + fmt.Sprintf("**[%s]**The pausing(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) **started**.\n", scaling.Region, scaling.Id, scaling.Status, scaling.ClusterId, scaling.TenantName, scaling.TenantId)
				if scaling.Status == "failed" && scaling.Message != "" {
					pauseText += ("**Error Message:** " + scaling.Message + "\n")
				}
				count++
			}
		}
	}
	if count > 0 {
		pauseText += "\n"
	}
	if err != nil {
		return "", err
	}
	for _, scaling := range finishedScalings {
		tenant, exist := activeTenantMap[scaling.TenantId]
		if scaling.Type == "pause" && exist && tenant.Plan == params.PlanType {
			if activeTenantMap[scaling.TenantId].Alias != "" {
				scaling.TenantName = activeTenantMap[scaling.TenantId].Alias
			}
			pauseText = pauseText + fmt.Sprintf("**[%s]**The pausing(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) **finished**.\n", scaling.Region, scaling.Id, scaling.Status, scaling.ClusterId, scaling.TenantName, scaling.TenantId)
			if scaling.Status == "failed" && scaling.Message != "" {
				pauseText += ("**Error Message:** " + scaling.Message + "\n")
			}
			count++
		}
	}
	if count > 0 {
		pauseText += "\n"
	}
	if err != nil {
		return "", err
	}
	count = 0
	for _, scaling := range longLastScalings {
		tenant, exist := activeTenantMap[scaling.TenantId]
		if scaling.Type == "pause" && exist && tenant.Plan == params.PlanType {
			cluster, exist := activeClusterMap[scaling.ClusterId]
			fStatusIn := func(c model.Cluster) bool {
				statu := []string{"cleared", "deleted", "deletecomplete", "unknown", "normal", "created", "done"}
				ret := false
				for _, status := range statu {
					if c.Status == status {
						ret = true
					}
				}
				return ret
			}
			if exist && !fStatusIn(cluster) && scaling.Status != "done" {
				if activeTenantMap[scaling.TenantId].Alias != "" {
					scaling.TenantName = activeTenantMap[scaling.TenantId].Alias
				}
				pauseText = pauseText + fmt.Sprintf("**[%s]**The pausing(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) lasts more than **3** hours, please take a look.\n", scaling.Region, scaling.Id, scaling.Status, scaling.ClusterId, scaling.TenantName, scaling.TenantId)
				if scaling.Status == "failed" && scaling.Message != "" {
					scalingText += ("**Error Message:** " + scaling.Message + "\n")
				}
				count++
			}
		}
	}
	if pauseText != "" {
		pauseText = "**Cluster Pausings:**\n" + pauseText
		if messageText != "" {
			pauseText = "\n --------------\n" + pauseText
		}
	}
	messageText += pauseText

	// Cluster Resuming
	resumeText := ""
	if err != nil {
		return "", err
	}
	count = 0
	for _, scaling := range startedScalings {
		tenant, exist := activeTenantMap[scaling.TenantId]
		if scaling.Type == "resume" && tenant.Plan == params.PlanType {
			if _, exist = activeClusterMap[scaling.ClusterId]; exist {
				if activeTenantMap[scaling.TenantId].Alias != "" {
					scaling.TenantName = activeTenantMap[scaling.TenantId].Alias
				}
				resumeText = resumeText + fmt.Sprintf("**[%s]**The resuming(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) **started**.\n", scaling.Region, scaling.Id, scaling.Status, scaling.ClusterId, scaling.TenantName, scaling.TenantId)
				if scaling.Status == "failed" && scaling.Message != "" {
					scalingText += ("**Error Message:** " + scaling.Message + "\n")
				}
				count++
			}
		}
	}
	if count > 0 {
		resumeText += "\n"
	}
	if err != nil {
		return "", err
	}
	for _, scaling := range finishedScalings {
		tenant, exist := activeTenantMap[scaling.TenantId]
		if scaling.Type == "resume" && exist && tenant.Plan == params.PlanType {
			if activeTenantMap[scaling.TenantId].Alias != "" {
				scaling.TenantName = activeTenantMap[scaling.TenantId].Alias
			}
			resumeText = resumeText + fmt.Sprintf("**[%s]**The resuming(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) **finished**.\n", scaling.Region, scaling.Id, scaling.Status, scaling.ClusterId, scaling.TenantName, scaling.TenantId)
			if scaling.Status == "failed" && scaling.Message != "" {
				resumeText += ("**Error Message:** " + scaling.Message + "\n")
			}
			count++
		}
	}
	if count > 0 {
		resumeText += "\n"
	}
	if err != nil {
		return "", err
	}
	count = 0
	for _, scaling := range longLastScalings {
		tenant, exist := activeTenantMap[scaling.TenantId]
		if scaling.Type == "scale" && exist && tenant.Plan == params.PlanType {
			cluster, exist := activeClusterMap[scaling.ClusterId]
			fStatusIn := func(c model.Cluster) bool {
				statu := []string{"cleared", "deleted", "deletecomplete", "unknown", "normal", "created", "done"}
				ret := false
				for _, status := range statu {
					if c.Status == status {
						ret = true
					}
				}
				return ret
			}
			if exist && !fStatusIn(cluster) && scaling.Status != "done" {
				if activeTenantMap[scaling.TenantId].Alias != "" {
					scaling.TenantName = activeTenantMap[scaling.TenantId].Alias
				}
				resumeText = resumeText + fmt.Sprintf("**[%s]**The resuming(%d)[status: **%s**] of cluster(%d) of tenant[%s]-(%d) lasts more than **3** hours, please take a look.\n", scaling.Region, scaling.Id, scaling.Status, scaling.ClusterId, scaling.TenantName, scaling.TenantId)
				if scaling.Status == "failed" && scaling.Message != "" {
					resumeText += ("**Error Message:** " + scaling.Message + "\n")
				}
				count++
			}
		}
	}
	if resumeText != "" {
		resumeText = "**Cluster Resumings:**\n" + resumeText
		if messageText != "" {
			resumeText = "\n --------------\n" + resumeText
		}
	}
	messageText += resumeText

	// Sum up
	if strings.Contains(messageText, "failed") {
		messageText = strings.ReplaceAll(messageText, "**failed**", "❌**failed**❌")
		messageText = "❌**FAILURE DETECTED**❌\n" + messageText
	}
	if params.PlanType == "poc" {
		lastFetchPOCTenants = make(map[uint64]bool)
		for tid, tenant := range activeTenantMap {
			if tenant.Plan == "poc" {
				lastFetchPOCTenants[tid] = true
			}
		}
	}
	return messageText, nil
}

func generateTextForOndemand() string {
	return ""
}

// Different Region has differenet report
func generateDailyReportsForDevTier() map[string]string {
	return nil
}
