package webScene

import (
	"fmt"
	"math/rand"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	"github.com/dailymotion/allure-go"
	"github.com/stretchr/testify/assert"
	"github.com/tidbcloud/qa-PlatformAPIAuto/common"
	"github.com/tidbcloud/qa-PlatformAPIAuto/webScene/br"
	"github.com/tidbcloud/qa-PlatformAPIAuto/webScene/br/aws"
	iamCases "github.com/tidbcloud/qa-PlatformAPIAuto/webScene/cbp/iam"
	platformCases "github.com/tidbcloud/qa-PlatformAPIAuto/webScene/cbp/platform"

	dpCommon "github.com/tidbcloud/qa-PlatformAPIAuto/webScene/common"
	"github.com/tidbcloud/qa-gourd/ProductModel"
	"github.com/tidbcloud/qa-gourd/ProductService"
	"github.com/tidbcloud/qa-gourd/handler"
	"github.com/tidbcloud/qa-gourd/util"
	//"time"
)

func (w *WebE2ECase) DedicatedCreateCluster(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		if w.WebRequestInfo.Cluster.ClusterId == "" {
			w.Reporter.StepReport("create cluster",
				func() {
					_, err := w.WebRequestInfo.CreateMinDedicatedCluster()
					if err != nil {
						ProductService.SendStopBillsMeteringSignal("Dedicated")
						assert.FailNow(w.Reporter.T, err.Error())
					} else {
						// send 2 mins of set password sleeping time cost.
						common.SetLastBillsEventTime(time.Now().Add(-time.Minute * 2))
					}
				})
		}
		w.Reporter.StepReport("check cluster node", func() {
			w.CheckActualNodeInfo()
		})
	})
}

func (w *WebE2ECase) DedicatedUpdatePassword(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		w.CheckUpdatePassword()
	})
}

func (w *WebE2ECase) DedicatedFilterAndConnectOperation(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		w.CheckFilterAndConnectOperation()
	})
}

func (w *WebE2ECase) DedicatedVpcOperation(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		w.CheckVPCOperation(false)
	})
}

func (w *WebE2ECase) DedicatedVpcCrossRegionConnection(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		w.CheckVPCOperation(true)
	})
}

func (w *WebE2ECase) DedicatedAuditLog(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		w.Reporter.StepReport("SetAuditLog", func() {
			w.SetAuditLog()
		})
		w.Reporter.StepReport("AuditLogSelectFromTidb", func() {
			w.AuditLogSelectFromTidb()
		})
		util.SecondTimeWait(10, 30, "Wait For Audit Log Reload")
		w.Reporter.StepReport("TestDeleteCluster", func() {
			w.WebRequestInfo.DeleteCluster()
			common.SendClusterDeletedCost(w.WebRequestInfo)
		})
		util.SecondTimeWait(5, 30, "Wait For Audit Log File Upload")
		w.Reporter.StepReport("CheckAuditLog", func() {
			w.CheckAuditLog()
		})
	})
}

func (w *WebE2ECase) DedicatedPrivateLinkConnect(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		w.CheckPrivateLinkConnect()
	})

}

func (w *WebE2ECase) DedicatedPauseAndResume(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		w.Reporter.StepReport("pause", func() {
			w.Pause()
		})
		w.Reporter.StepReport("resume", func() {
			w.Resume()
		})
		w.Reporter.StepReport("public connect", func() {
			w.CheckFilterAndConnectOperation()
		})
	})
}

func (w *WebE2ECase) DedicatedScaleCluster(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		w.Reporter.StepReport("scale", func() {
			w.CheckScaleCluster()
		})
	})
}

func (w *WebE2ECase) DedicatedNewProject(t *testing.T) {
	t.Parallel()
	wn := w.DeepCopy()
	wn.SetReporter(t)
	wn.Reporter.SceneReport(func() {
		var projectId, cidr, cidrId string
		var err error
		wn.Reporter.StepReport("create normal project", func() {
			projectId = wn.WebRequestInfo.CreateNewProject(false)
		})
		//切换project
		wn.WebRequestInfo.User.ProjectId = projectId
		wn.Reporter.StepReport("query default cidr", func() {
			cidr = wn.WebRequestInfo.FindDefaultCIDR()
		})
		wn.Reporter.StepReport("create region cidr", func() {
			cidrId = wn.CreateRegionCidr(cidr)
			wn.DeleteCIDRById(cidrId, false)
			cidrId = wn.WebRequestInfo.CreateCIDR(cidr, false)
		})
		wn.Reporter.StepReport("create cluster",
			func() {
				_, err = wn.WebRequestInfo.CreateMinDedicatedClusterByProvider(wn.WebRequestInfo.Cluster.Provider, wn.WebRequestInfo.Cluster.Region) //因为有随机region 的情况，需要确保这里使用cidr创建的region
				assert.Nil(t, err)
				wn.DeleteCIDRById(cidrId, true)
			})
		if err == nil {
			wn.Reporter.StepReport("delete cluster", func() {
				wn.WebRequestInfo.DeleteCluster()
			})
			time.Sleep(30 * time.Second)
			wn.Reporter.StepReport("delete project", func() {
				wn.WebRequestInfo.DeleteProjectById(projectId)
			})
		}
	})
}

func (w *WebE2ECase) DedicatedCIDRTest(t *testing.T) {
	t.Parallel()
	rand.Seed(time.Now().UnixNano())
	cidrArray := getCIDRArray(w.WebRequestInfo.Cluster.Provider)
	for _, cidr := range cidrArray {
		cidr := cidr
		t.Run(fmt.Sprintf("cidr: %s", cidr), func(t *testing.T) {
			t.Parallel()
			wn := w.DeepCopy()
			wn.SetReporter(t)
			wn.Reporter.SceneReport(func() {
				var projectId string
				var err error
				wn.Reporter.StepReport("create normal project", func() {
					projectId = wn.WebRequestInfo.CreateNewProject(false)
				})
				//切换project
				wn.WebRequestInfo.User.ProjectId = projectId
				wn.Reporter.StepReport("create region cidr", func() {
					wn.CreateRegionCidr(cidr)
				})
				wn.Reporter.StepReport("create cluster",
					func() {
						_, err = wn.WebRequestInfo.CreateMinDedicatedClusterByProvider(wn.WebRequestInfo.Cluster.Provider, wn.WebRequestInfo.Cluster.Region) //因为有随机region 的情况，需要确保这里使用cidr创建的region
						assert.Nil(t, err)
					})
				if err == nil {
					wn.Reporter.StepReport("delete cluster", func() {
						wn.WebRequestInfo.DeleteCluster()
					})
					time.Sleep(30 * time.Second)
					wn.Reporter.StepReport("delete project", func() {
						wn.WebRequestInfo.DeleteProjectById(projectId)
					})
				}
			})
		})
	}
}

func (w *WebE2ECase) DedicatedNewCMEKProject(t *testing.T) {
	t.Parallel()
	wn := w.DeepCopy()
	wn.SetReporter(t)
	if !wn.WebRequestInfo.CheckCMEKIsSupport() {
		return
	}

	wn.Reporter.SceneReport(func() {
		var err error
		projectId := wn.WebRequestInfo.CreateNewProject(true)
		wn.Reporter.StepReport("create cmek enabled project", func() {
			require.NotEqual(t, "", projectId)
		})
		//切换project
		wn.WebRequestInfo.User.ProjectId = projectId
		wn.Reporter.StepReport("update cluster key", func() {
			require.True(t, wn.WebRequestInfo.UpdateClusterCMEKKey())
		})
		wn.Reporter.StepReport("create region cidr", func() {
			rand.Seed(time.Now().UnixNano())
			cidr := generateRandomCidr()
			wn.CreateRegionCidr(cidr)
		})
		wn.Reporter.StepReport("create cluster",
			func() {
				_, err = wn.WebRequestInfo.CreateMinDedicatedClusterByProvider(wn.WebRequestInfo.Cluster.Provider, wn.WebRequestInfo.Cluster.Region) //因为有随机region 的情况，需要确保这里使用cidr创建的region
				assert.Nil(t, err)
			})
		if err == nil {
			wn.Reporter.StepReport("delete cluster", func() {
				wn.WebRequestInfo.DeleteCluster()
			})
			time.Sleep(30 * time.Second)
			wn.Reporter.StepReport("delete project", func() {
				wn.WebRequestInfo.DeleteProjectById(projectId)
			})
		}
	})
}

func (w *WebE2ECase) DedicatedDashboard(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		w.Reporter.StepReport("TestDiagnosis", func() {
			w.CheckDedicatedDashboard()
		})

		// check monitoring
		w.Reporter.StepReport("CheckMetrics",
			func() {
				w.CheckMonitoringMetric(10 * 60)
			})
		//check alerts
		w.Reporter.StepReport("CheckAlerts",
			func() {
				w.CheckAlerts(10 * 60)
			})

		//check events
		w.Reporter.StepReport("CheckEvents",
			func() {
				w.CheckEvents(24 * 60 * 60)
			})
	})
}

// TODO: need use new arch
func (w *WebE2ECase) DedicatedEnableAndDisablePublicIp(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		w.CheckEnableAndDisablePublicIp()
	})
}

// TODO: need use new arch
func (w *WebE2ECase) DedicatedRunTPCC(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		w.Reporter.StepReport("AddTrafficFilter", func() {
			w.WebRequestInfo.AddTrafficFilter("0.0.0.0/0", false)
		})
		w.Reporter.StepReport("close pitr", func() {
			brTest := &aws.BRSmokeUseCaseSceneTest{
				CommonSceneTest: br.CommonSceneTest{
					SceneTest: dpCommon.SceneTest{
						T:                t,
						DbaasRequestInfo: common.GetDbassRequestInfo(t),
						ClusterId:        w.WebRequestInfo.Cluster.ClusterId,
					},
				},
			}
			brTest.ClosePiTR()
		})

		w.Reporter.StepReport("ImportTPCCData",
			func() {
				if err := w.WebRequestInfo.ImportTPCCData(30 * time.Minute); err != nil {
					allure.FailNow(err)
				}
			})

		w.Reporter.StepReport("RunTPCCWorkload",
			func() {
				if err := w.WebRequestInfo.RunTPCCWorkload(15*time.Minute, w.WebRequestInfo.NewTPCCWorkloadInfo()); err != nil {
					allure.FailNow(err)
				}
			})
	})
}

//// TODO: need use new arch
//func (w *WebE2ECase) EKSInfraProviderUpgrade(t *testing.T) {
//	var provider = "aws"
//
//	deploymentName := common.GetDeploymentName()
//	configMapName := common.GetConfigMapName()
//	label := common.GetLabel()
//
//	allure.Test(t,
//		allure.Epic("TestInfraProviderUpgrade"),
//		allure.Feature("SetEKSSeedContext"),
//		allure.Description("SetEKSSeedContext"),
//		allure.Action(func() {
//			common.SetEKSSeedContext(t)
//		}))
//
//	allure.Test(t,
//		allure.Epic("TestInfraProviderUpgrade"),
//		allure.Feature("CheckDeployNewEKSConfigMap"),
//		allure.Description("CheckDeployNewEKSConfigMap"),
//		allure.Action(func() {
//			common.DeployEKSConfigMap(t, configMapName, label, common.FeatureGates, common.ExpFeatureGates)
//		}))
//
//	allure.Test(t,
//		allure.Epic("TestInfraProviderUpgrade"),
//		allure.Feature("CheckDeployNewEKSProvider"),
//		allure.Description("CheckDeployNewEKSProvider"),
//		allure.Action(func() {
//			common.DeployEKSInfraProvider(t, deploymentName, common.InfraImage, configMapName)
//		}))
//
//	allure.Test(t,
//		allure.Epic("TestInfraProviderUpgrade"),
//		allure.Feature("RunWorkload"),
//		allure.Description("RunWorkload"),
//		allure.Action(func() {
//
//		}))
//
//	allure.Test(t,
//		allure.Epic("TestInfraProviderUpgrade"),
//		allure.Feature("CheckClusterUseNewEKSInfraProvider"),
//		allure.Description("CheckClusterUseNewEKSInfraProvider"),
//		allure.Action(func() {
//			common.CheckClusterUseNewEKSInfraProvider(t, label, deploymentName, w.WebRequestInfo.Cluster.ClusterId)
//		}))
//
//	allure.Test(t,
//		allure.Epic("TestInfraProviderUpgrade"),
//		allure.Feature("CheckPodUptime"),
//		allure.Description("CheckPodUptime"),
//		allure.Action(func() {
//			common.CheckPodUptime(t, provider, w.WebRequestInfo.Cluster.ClusterId, "all", "")
//		}))
//}

func (w *WebE2ECase) DedicatedTierDataAPP(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		if w.WebRequestInfo.Cluster.Provider == ProductModel.GCP {
			w.Reporter.StepReport("DedicatedTierDataAPP - CanNotRunInGCP",
				func() {
					assert.True(w.Reporter.T, false)
				})
			return
		}
		platformCases.RunAllDataAPPSceneTest(w.WebRequestInfo, w.URLInfoMap, &w.Reporter)
	})
}

/* Platform Chat2Query Scene */
func (w *WebE2ECase) DedicatedTierChat2QueryBasicCheck(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		if w.WebRequestInfo.Cluster.Provider == ProductModel.GCP {
			w.Reporter.StepReport("DedicatedTierChat2QueryBasicCheck - CanNotRunInGCP",
				func() {
					assert.True(w.Reporter.T, false)
				})
			return
		}
		platformCases.RunChat2QueryBasicCheckSceneTest(w.WebRequestInfo, w.URLInfoMap, &w.Reporter)
	})
}

/*
*
check generous dml and ddl
*/
func (w *WebE2ECase) DedicatedTierRunSqlByChat2Query(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		if w.WebRequestInfo.Cluster.Provider == ProductModel.GCP {
			w.Reporter.StepReport("DedicatedTierRunSqlByChat2Query - CanNotRunInGCP",
				func() {
					assert.True(w.Reporter.T, false)
				})
			return
		}
		platformCases.RunChat2QuerySQLCheckSceneTest(w.WebRequestInfo, w.URLInfoMap, &w.Reporter)
	})
}

func (w *WebE2ECase) DedicatedTierSQLUser(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		iamCases.RunSQLUserTest(w.WebRequestInfo, w.URLInfoMap, &w.Reporter)
	})
}

func (w *WebE2ECase) DedicatedTierShadowAccount(t *testing.T) {
	w.SetReporter(t)
	w.Reporter.SceneReport(func() {
		if w.WebRequestInfo.Cluster.Provider == ProductModel.GCP || handler.EnvFile == ProductModel.Prod {
			w.Reporter.StepReport("DedicatedTierShadowAccount - CanNotRunInGCPorProd",
				func() {
					assert.True(w.Reporter.T, false)
				})
			return
		}
		iamCases.RunShadowAccountSceneTest(w.WebRequestInfo, w.URLInfoMap, &w.Reporter)
	})
}
