package main

import (
	"context"
	"dataservices/commons/config"
	"dataservices/commons/httpclient"
	"dataservices/commons/utils"
	dto "dataservices/internal/dto/dataapi"
	"dataservices/internal/entity"
	service "dataservices/internal/service/central"
	json2 "encoding/json"
	"flag"
	"fmt"
	"strconv"

	svc_central "dataservices/internal/service/central"

	"github.com/pingcap/log"
	"go.uber.org/zap"
)

const (
	host = "http://127.0.0.1:8080"
)

type Data struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data"`
}

const defaultConfigPath = "/etc/dbaas/config.yaml"

func main() {
	var configPath string
	flag.StringVar(&configPath, "config-path", defaultConfigPath, "DBaaS configuration file path")
	flag.Parse()
	ctx := context.Background()
	config.InitConfig(configPath)

	// token := "bing.wang@pingcap.com"

	orgId := 30061
	projectId := 2353490
	// appId := 1290010
	userId := 70166
	svc_central.CheckUserHasCreateWriteKeyPermission(ctx, uint64(userId), uint64(orgId), uint64(projectId))
	// deploy dataapp
	// testListDataAppDeployLogs(token, orgId, projectId, appId)
	//testGetDataAppDeploySetting(token, orgId, projectId, appId)
	// testEnableAutoDeploy(token, orgId, projectId, appId)
	// testDeployDataApp(token, orgId, projectId, appId)

	// data app test
	//testListDataApiApps(token, orgId, projectId)
	//appIdStr := testCreateDataApiApp(token, orgId, projectId)
	//log.Info(fmt.Sprintf("CreateDataApp id###########:%s", appIdStr))

	//appId, _ := strconv.Atoi(appIdStr)
	//testGetDataApiApp(token, orgId, projectId, appId)
	//testUpdateDataApiApp(token, orgId, projectId, appId)
	//testDeleteDataApiApp(token, orgId, projectId, appId)

	// apikey test
	//appId := 5
	//apikeyId := testCreateApiKey(token, orgId, projectId, appId)
	//testDeleteApiKeys(token, orgId, projectId, appId, apikeyId)
	//testListApiKeys(token, orgId, projectId, appId)

	// endpoint config test
	//appId := 5
	//endpointIdStr := testCreateEndpoint(token, orgId, projectId, appId)
	//endpointId, _ := strconv.Atoi(endpointIdStr)
	//testUpdateEndpoint(token, orgId, projectId, appId, endpointId)
	//testGetEndpoint(token, orgId, projectId, appId, endpointId)
	//testDeleteEndpoint(token, orgId, projectId, appId, endpointId)
	//testListEndpoints(token, orgId, projectId, appId)
	//testCreateEndpoint(token, orgId, projectId, appId)

	// deploy endpoint test
	//appId := 5
	//endpointIdStr := testCreateEndpoint(token, orgId, projectId, appId)
	//endpointId, _ := strconv.Atoi(endpointIdStr)
	//testOnlineEndpoint(token, orgId, projectId, appId, endpointId)
	//testListOnlineEndpoint(token, orgId, projectId, appId)
	//testGetEndpointVersions(token, orgId, projectId, appId, endpointId)
	//testOfflineEndpoint(token, orgId, projectId, appId, endpointId)
	//testDeleteEndpoint(token, orgId, projectId, appId, endpointId)

}
func testGenApiKeys() {
	log.Info("Key is " + utils.RandNumStr(32))
	log.Info("Iv is " + utils.RandNumStr(16))
}

func testCreateDataApiApp(token string, orgId int, projectId int) string {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps"

	resp, code, err := httpclient.PostWithHeader(url, nil, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
	data := Data{}
	json2.Unmarshal([]byte(resp), &data)
	log.Info(fmt.Sprintf("id###########:%v", data.Data))
	return fmt.Sprintf("%v", data.Data)
}

func testUpdateDataApiApp(token string, orgId int, projectId int, appId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId)
	reqStruct := &entity.UpdateDataAppParam{
		AppName:          "auto test app update",
		DeploymentRegion: "global",
	}

	resp, code, err := httpclient.PutWithHeader(url, reqStruct, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testDeleteDataApiApp(token string, orgId int, projectId int, appId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId)

	resp, code, err := httpclient.DeleteWithHeader(url, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testDeployDataApp(token string, orgId int, projectId int, appId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/central/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/deploy"
	params := map[string]string{"deploy_name": "test"}
	resp, code, err := httpclient.PostWithHeader(url, &params, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}
func testEnableAutoDeploy(token string, orgId int, projectId int, appId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/central/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/deploy/github/enable_auto_deploy"
	params := map[string]string{"github_auth_request_id": "test_id", "repository_id": "test123", "branch": "master", "directory": "/"}
	resp, code, err := httpclient.PostWithHeader(url, &params, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testListDataAppDeployLogs(token string, orgId int, projectId int, appId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/central/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/deploy-logs"
	resp, code, err := httpclient.GetWithHeader(url, nil, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testGetDataAppDeploySetting(token string, orgId int, projectId int, appId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/central/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/deploy/config"
	resp, code, err := httpclient.GetWithHeader(url, nil, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testListDataApiApps(token string, orgId int, projectId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps"
	params := map[string]string{"apptype": string(entity.DataAppTypeDataapi)}
	resp, code, err := httpclient.GetWithHeader(url, &params, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}
func testGetDataApiApp(token string, orgId int, projectId int, appId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId)
	resp, code, err := httpclient.GetWithHeader(url, nil, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testListApiKeys(token string, orgId int, projectId int, appId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/apikeys"
	resp, code, err := httpclient.GetWithHeader(url, nil, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testCreateApiKey(token string, orgId int, projectId int, appId int) uint64 {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/apikeys"

	body := map[string]string{"description": "autotest apikey"}
	resp, code, err := httpclient.PostWithHeader(url, body, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
	apikey := dto.CreateAPIKeyRes{}
	json2.Unmarshal([]byte(resp), &apikey)
	log.Info(fmt.Sprintf("id###########:%v", apikey.Data.Id))
	return apikey.Data.Id
}

func testDeleteApiKeys(token string, orgId int, projectId int, appId int, apikeyId uint64) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/apikeys/" + strconv.FormatInt(int64(apikeyId), 10)
	resp, code, err := httpclient.DeleteWithHeader(url, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testListEndpoints(token string, orgId int, projectId int, appId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/endpoints"
	resp, code, err := httpclient.GetWithHeader(url, nil, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testCreateEndpoint(token string, orgId int, projectId int, appId int) string {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/endpoints"

	settings := map[string]interface{}{"timeout": 2000, "return_type": "json", "row_limit": 200}
	args := map[string]interface{}{"name": "id", "type": "number", "required": 1, "default": "1", "description": ""}
	body := map[string]interface{}{"name": "endpoint-autotest" + utils.RandNumStr(4), "description": "autotest", "endpoint": "/autotest" + utils.RandNumStr(4), "method": "get", "clusterId": 90909, "database": "test", "sql_template": "show tables;", "settings": settings, "args": args}
	resp, code, err := httpclient.PostWithHeader(url, body, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
	data := Data{}
	json2.Unmarshal([]byte(resp), &data)
	log.Info(fmt.Sprintf("id###########:%v", data.Data))
	return fmt.Sprintf("%v", data.Data)
}

func testUpdateEndpoint(token string, orgId int, projectId int, appId int, endpointId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/endpoints/" + strconv.Itoa(endpointId)

	settings := map[string]interface{}{"timeout": 2000, "return_type": "json", "row_limit": 200}
	body := map[string]interface{}{"name": "endpoint-autotest" + utils.RandNumStr(4), "description": "autotest", "endpoint": "/autotest-update" + utils.RandNumStr(4), "method": "get", "database": "test", "sql_template": "show tables;", "settings": settings}
	resp, code, err := httpclient.PutWithHeader(url, body, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testGetEndpoint(token string, orgId int, projectId int, appId int, endpointId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/endpoints/" + strconv.Itoa(endpointId)

	resp, code, err := httpclient.GetWithHeader(url, nil, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testDeleteEndpoint(token string, orgId int, projectId int, appId int, endpointId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/endpoints/" + strconv.Itoa(endpointId)

	resp, code, err := httpclient.DeleteWithHeader(url, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testOnlineEndpoint(token string, orgId int, projectId int, appId int, endpointId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/endpoints/" + strconv.Itoa(endpointId) + "/online"

	resp, code, err := httpclient.PostWithHeader(url, nil, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testOfflineEndpoint(token string, orgId int, projectId int, appId int, endpointId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/endpoints/" + strconv.Itoa(endpointId) + "/offline"

	resp, code, err := httpclient.PutWithHeader(url, nil, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testGetEndpointVersions(token string, orgId int, projectId int, appId int, endpointId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/endpoints/" + strconv.Itoa(endpointId) + "/versions"

	resp, code, err := httpclient.GetWithHeader(url, nil, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}

func testListOnlineEndpoint(token string, orgId int, projectId int, appId int) {
	header := map[string]string{"test-email": token}
	url := host + "/api/v1/dataservices/orgs/" + strconv.Itoa(orgId) + "/projects/" + strconv.Itoa(projectId) + "/apps/" + strconv.Itoa(appId) + "/endpoints/online/records"

	resp, code, err := httpclient.GetWithHeader(url, nil, &header)
	if err != nil {
		log.Error("fail to get response ", zap.Error(err))
	}
	log.Info("resp code is  " + strconv.Itoa(code) + " body is " + resp)
}
func testO11yRegionUrl() {

	ctx := context.Background()
	var orgId uint64 = 1369847559691517271
	queryParam := entity.DataUsageQueryParam{
		Type:      "daily",
		Class:     "byEndpointRequest",
		DataAppId: 1200324,
		Start:     1686441600,
		End:       1689120000,
		Step:      86400,
	}
	resp, err := service.ListDataAppUsage(ctx, queryParam, 0, orgId)

	log.Info("ListDataAppUsage :", zap.Any("ss", resp.Data.Result), zap.Error(err))
}
