package openAPIScene

import (
	"fmt"
	l4g "github.com/alecthomas/log4go"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/tidbcloud/qa-PlatformAPIAuto/common"
	"github.com/tidbcloud/qa-gourd/ProductModel"
	"github.com/tidbcloud/qa-gourd/handler"
	"regexp"
	"strconv"
	"strings"
	"testing"
)

func (o *OpenAPIE2ECase) DedicatedCreateCluster(t *testing.T) {
	o.SetReporter(t)
	var cluster *ProductModel.ClusterItem
	var err error
	o.Reporter.SceneReport(func() {
		if o.OpenAPIRequestInfo.Cluster.ClusterId == "" {
			o.Reporter.StepReport("create cluster", func() {
				cluster, err = o.OpenAPIRequestInfo.CreateMinDedicatedCluster()
				if err != nil {
					assert.FailNow(o.Reporter.T, err.Error())
				}
			})
			o.Reporter.StepReport("check cluster", func() {
				o.CheckClusterItem()
			})
			o.Reporter.StepReport("create same name cluster", func() {
				cluster = o.OpenAPIRequestInfo.GetClusterInfo()
				tiflashCount := 0
				tiflashStorageSize := 0
				tiflashNodeSize := ""
				if cluster.Config.Components.Tiflash != nil {
					tiflashCount = int(cluster.Config.Components.Tiflash.NodeQuantity)
					tiflashStorageSize = int(cluster.Config.Components.Tiflash.StorageSizeGib)
					tiflashNodeSize = cluster.Config.Components.Tiflash.NodeSize
				}
				_, clusterRes := o.OpenAPIRequestInfo.CreatCluster(cluster.Name, cluster.CloudProvider, cluster.Region,
					int(cluster.Config.Components.Tidb.NodeQuantity),
					int(cluster.Config.Components.Tikv.NodeQuantity),
					tiflashCount,
					int(cluster.Config.Components.Tikv.StorageSizeGib),
					tiflashStorageSize,
					cluster.Config.Components.Tidb.NodeSize,
					cluster.Config.Components.Tikv.NodeSize,
					tiflashNodeSize)
				l4g.Info("CreatCluster:%s", clusterRes.JSON().Raw())
				code := int(clusterRes.Status(400).JSON().Object().Value("code").Number().Raw())
				assert.Equal(t, 60100001, code)
			})
		}
	})
}

func (o *OpenAPIE2ECase) DedicatedListClusterInProjcet(t *testing.T) {
	o.SetReporter(t)
	o.Reporter.SceneReport(func() {
		o.CheckListClusterInProject()
	})
}

func (o *OpenAPIE2ECase) DedicatedModifyCluster(t *testing.T) {
	o.SetReporter(t)
	o.Reporter.SceneReport(func() {
		o.CheckModifyCluster()
	})
}

func (o *OpenAPIE2ECase) DedicatedPublicConnect(t *testing.T) {
	o.SetReporter(t)
	o.Reporter.SceneReport(func() {
		o.CheckPublicConnect()
	})
}

func (o *OpenAPIE2ECase) DedicatedPauseAndResume(t *testing.T) {
	o.SetReporter(t)
	o.Reporter.SceneReport(func() {
		o.CheckPauseAndResume()
	})
}

func (o *OpenAPIE2ECase) DedicatedMultiAccessPoint(t *testing.T) {
	if o.OpenAPIRequestInfo.Cluster.Provider != "AWS" {
		return
	}
	o.SetReporter(t)
	o.Reporter.SceneReport(func() {
		var ac1, ac2 *common.Accesspoint
		o.Reporter.StepReport("add accesspoint", func() {
			ac1 = o.AddAccessPoint(1, "actest1")
			ac2 = o.AddAccessPoint(2, "actest2")
			if ac1 == nil || ac2 == nil {
				return
			}
			o.CheckAccessPointList([]*common.Accesspoint{ac1, ac2}, true)
		})
		o.Reporter.StepReport("check webconsole accesspoint display", func() {
			o.CheckAccessPointList([]*common.Accesspoint{ac1, ac2}, false)
		})
		o.Reporter.StepReport("check public connect", func() {
			o.CheckAccessPointPublicConnect(ac1, "0.0.0.0/0")
			o.CheckAccessPointPublicConnect(ac2, "")
		})
		w := o.OpenAPIRequestInfo.GetWebRequestInfo()
		if w.GetVPCSupportRegion() {
			o.Reporter.StepReport("check accespoint privatelink", func() {
				endpoint, err := w.CreateAWSVPCEndpoint(ac1.PrivateEndpoint.PrivateLinkService.ServiceName)
				if err != nil {
					require.Fail(t, "create endpoint failed")
				}
				o.CheckAccessPointPrivateLink(endpoint, ac1)
				w.DeleteVPCEndpoint(endpoint)
			})
		}
		o.Reporter.StepReport("delete accepoint", func() {
			o.DeleteAccessPoint(ac1)
			o.DeleteAccessPoint(ac2)
		})
	})
}

func (o *OpenAPIE2ECase) DedicatedNewCMEKProject(t *testing.T) {
	t.Parallel()
	on := o.DeepCopy()
	on.SetReporter(t)
	webRequestInfo := on.OpenAPIRequestInfo.GetWebRequestInfo()
	if !webRequestInfo.CheckCMEKIsSupport() {
		return
	}
	on.Reporter.SceneReport(func() {
		var projectId string
		on.Reporter.StepReport("create cmek enabled project", func() {
			projectId = webRequestInfo.CreateNewProject(true)
		})
		//切换project
		on.OpenAPIRequestInfo.User.ProjectId = projectId
		on.Reporter.StepReport("update cluster key", func() {
			require.True(t, on.OpenAPIRequestInfo.UpdateClusterCMEKKey())
		})
		on.Reporter.StepReport("delete project", func() {
			webRequestInfo.DeleteProjectById(projectId)
			on.OpenAPIRequestInfo.DeleteAPIKey()
		})
	})
}

func (o *OpenAPIE2ECase) DedicatedPrivateLink(t *testing.T) {
	o.SetReporter(t)
	o.Reporter.SceneReport(func() {
		if !o.OpenAPIRequestInfo.GetWebRequestInfo().GetVPCSupportRegion() {
			//其他region 不支持
			o.Reporter.StepReport(fmt.Sprintf("当前region: %s 不支持,请手工确认", o.OpenAPIRequestInfo.Cluster.Region),
				func() {
					assert.True(o.Reporter.T, false)
				})
			return
		}
		var endpointService *common.PrivateEndpointServiceResp
		o.Reporter.StepReport("create private endpoint service", func() {
			endpointService = o.CreateEndpointService()
		})
		o.Reporter.StepReport("check privatelink", func() {
			o.CheckPrivatelink(endpointService.PrivateEndpointService.DnsName, endpointService.PrivateEndpointService.Name)
		})
	})

}

func (o *OpenAPIE2ECase) DedicatedAllow4cTiKVNum(t *testing.T) {
	o.SetReporter(t)
	o.Reporter.SceneReport(func() {
		provider := o.OpenAPIRequestInfo.Cluster.Provider
		region := o.OpenAPIRequestInfo.Cluster.Region
		clusterId := o.OpenAPIRequestInfo.Cluster.ClusterId
		actualSupport := 0
		o.Reporter.StepReport("exceed tikv node create", func() {
			_, tikvStorageSizeGib, tiflashStorageSizeGib, tidbNodeSize, tikvNodeSize, tiflashNodeSize := o.OpenAPIRequestInfo.GetAvailableNodeSize(provider,
				region, 4)
			_, clusterRes := o.OpenAPIRequestInfo.CreatCluster("openapi-auto-4c-exceed-"+handler.APIConfigInfo.RunUser, provider, region, 2, 24, 0, tikvStorageSizeGib, tiflashStorageSizeGib, tidbNodeSize, tikvNodeSize, tiflashNodeSize)
			clusterRes.Status(400)
			clusterRes.JSON().Path("$.code").IsEqual(49900001)
			message := clusterRes.JSON().Path("$.message").String().Raw()
			if strings.Contains(message, "less than") {
				re := regexp.MustCompile(`node_quantity must be less than (\d+)`)
				match := re.FindStringSubmatch(message)
				actualSupport, _ = strconv.Atoi(match[1])
			} else if strings.Contains(message, "The node_quantity must be 3") {
				actualSupport = 3
			}

		})
		if actualSupport == 3 {
			o.Reporter.StepReport("whitelist is not enable in this org", func() {
				assert.True(t, false)
			})
			return
		}
		if actualSupport == 0 {
			o.Reporter.StepReport("An unexpected exception occurred!", func() {
				assert.True(t, false)
			})
			return
		}
		o.Reporter.StepReport(fmt.Sprintf("check %d 4c tikv node create", actualSupport-3), func() {
			_, err := o.OpenAPIRequestInfo.CreateDedicatedClusterByCPUAndRegionAndCount(provider, region, 4, 2, actualSupport-3, 0)
			assert.Nil(t, err)
			o.OpenAPIRequestInfo.DeleteCluster()
		})
		//set original
		o.OpenAPIRequestInfo.Cluster.ClusterId = clusterId
	})
}
