package e2e

import (
	"encoding/json"
	"fmt"
	"strings"
)

func ExecCentralApiKeyCase() {
	Central_CreateOrgApiKey()
	Central_ListOrgApiKeys()
	Central_UpdateOrgApiKey()
	Central_DeleteOrgApiKey()
	Central_CreateProjectOpenAPIKey()
	Central_ListProjectOpenApiKeys()
	Central_UpdateProjectApiKey()
	Central_DeleteProjectApiKey()

	Central_CreateScimBearerToken()
	Central_ListScimBearerTokens()

}

func Central_CreateOrgApiKey() {
	url := DevConsoleHost + "/api/v1/orgs/1440002/api_keys"

	var header = map[string]string{}
	header["Content-type"] = "application/json"
	header["Authorization"] = consoleAuthorization

	body := `{
			"role": "org:member",
			"description": "e2e create console org key"
		}`

	code, data, err := RestyExec("POST", url, header, body)
	if err != nil {
		code = 0
		data = err.Error()
	}

	pass := false
	if code == 200 {
		openApiKey := &OpenAPIKey{}
		err := json.Unmarshal([]byte(data), openApiKey)
		if err == nil && openApiKey.PublicKey != "" {
			pass = true
		}
	}

	SaveCase("Central_ApiKey", "CreateOrgApiKey", CaseDetail{
		Url:       url,
		Method:    "POST",
		ReqHeader: header,
		ReqBody:   body,
		Pass:      pass,
		RspCode:   code,
		RspData:   data,
	})
}

type OpenAPIKey struct {
	Id           string `json:"id,omitempty"`
	OrgId        string `json:"org_id,omitempty"`
	PublicKey    string `json:"public_key,omitempty"`
	PrivateKey   string `json:"private_key,omitempty"`
	Digest       string `json:"digest,omitempty"`
	Role         string `json:"role,omitempty"`
	Description  string `json:"description,omitempty"`
	CreatorEmail string `json:"creator_email,omitempty"`
	ProjectId    string `json:"project_id,omitempty"`
}

type OpenAPIKeys struct {
	Total int32         `json:"total,omitempty"`
	Items []*OpenAPIKey `json:"items,omitempty"`
}

func Central_ListOrgApiKeys() {
	url := DevConsoleHost + "/api/v1/orgs/1440002/api_keys?page=1&per_page=2"

	var header = map[string]string{}
	header["Content-type"] = "application/json"
	header["Authorization"] = consoleAuthorization

	code, data, err := RestyExec("GET", url, header, "")
	if err != nil {
		code = 0
		data = err.Error()
	}

	pass := false
	if code == 200 {
		openApiKeys := &OpenAPIKeys{}
		err := json.Unmarshal([]byte(data), openApiKeys)
		if err == nil && len(openApiKeys.Items) > 0 && len(openApiKeys.Items) <= 2 {
			pass = true
			for _, k := range openApiKeys.Items {
				if !strings.HasPrefix(k.Role, "org:") {
					pass = false
				}
			}
		}
	}

	SaveCase("Central_ApiKey", "ListOrgApiKeys", CaseDetail{
		Url:       url,
		Method:    "GET",
		ReqHeader: header,
		ReqBody:   "",
		Pass:      pass,
		RspCode:   code,
		RspData:   data,
	})
}

func Central_UpdateOrgApiKey() {
	listUrl := DevConsoleHost + "/api/v1/orgs/1440002/api_keys?page=1&per_page=2"

	var header = map[string]string{}
	header["Content-type"] = "application/json"
	header["Authorization"] = consoleAuthorization

	listCode, listData, err := RestyExec("GET", listUrl, header, "")
	if err != nil {
		listCode = 0
		listData = err.Error()
	}

	var k *OpenAPIKey
	if listCode == 200 {
		openApiKeys := &OpenAPIKeys{}
		err := json.Unmarshal([]byte(listData), openApiKeys)
		if err == nil && len(openApiKeys.Items) > 0 {
			k = openApiKeys.Items[0]
		}
	}

	var updateUrl, updateBody, updateData string
	var updateCode int
	var secListUrl, secListData string
	var secListCode int
	pass := false
	if k != nil {
		updateUrl = DevConsoleHost + fmt.Sprintf("/api/v1/orgs/1440002/api_keys/%s", k.Id)
		updateBody = `{
				"role": "org:billing_admin",
				"description": "e2e update console org key"

			}`
		updateCode, updateData, err = RestyExec("PATCH", updateUrl, header, updateBody)
		if err != nil {
			updateCode = 0
			updateData = err.Error()
		}
		if updateCode == 200 {
			secListUrl = DevConsoleHost + fmt.Sprintf("/api/v1/orgs/1440002/api_keys?public_key=%s", k.PublicKey)
			secListCode, secListData, err = RestyExec("GET", secListUrl, header, "")
			if err != nil {
				secListCode = 0
				secListData = err.Error()
			}
			if secListCode == 200 {
				openApiKeys := &OpenAPIKeys{}
				err := json.Unmarshal([]byte(secListData), openApiKeys)
				if err == nil && len(openApiKeys.Items) == 1 && openApiKeys.Items[0].PublicKey == k.PublicKey &&
					openApiKeys.Items[0].Role == "org:billing_admin" && openApiKeys.Items[0].Description == "e2e update console org key" {
					pass = true
				}
			}
		}
	}

	SaveCase("Central_ApiKey", "UpdateOrgApiKey", CaseDetail{
		Url:       updateUrl,
		Method:    "GET",
		ReqHeader: header,
		ReqBody:   updateBody,
		Pass:      pass,
		RspCode:   updateCode,
		RspData:   updateData,
		Extra: map[string]interface{}{
			"list_url":      listUrl,
			"list_code":     listCode,
			"list_data":     listData,
			"sec_list_url":  secListUrl,
			"sec_list_code": secListCode,
			"sec_list_data": secListData,
		},
	})
}

func Central_DeleteOrgApiKey() {
	listUrl := DevConsoleHost + "/api/v1/orgs/1440002/api_keys?page=1&per_page=2"

	var header = map[string]string{}
	header["Content-type"] = "application/json"
	header["Authorization"] = consoleAuthorization

	listCode, listData, err := RestyExec("GET", listUrl, header, "")
	if err != nil {
		listCode = 0
		listData = err.Error()
	}

	var k *OpenAPIKey
	if listCode == 200 {
		openApiKeys := &OpenAPIKeys{}
		err := json.Unmarshal([]byte(listData), openApiKeys)
		if err == nil && len(openApiKeys.Items) > 0 {
			k = openApiKeys.Items[0]
		}
	}

	var deleteUrl, deleteData string
	var deleteCode int
	var secListUrl, secListData string
	var secListCode int
	pass := false
	if k != nil {
		deleteUrl = DevConsoleHost + fmt.Sprintf("/api/v1/orgs/1440002/api_keys/%s", k.Id)
		deleteCode, deleteData, err = RestyExec("DELETE", deleteUrl, header, "")
		if err != nil {
			deleteCode = 0
			deleteData = err.Error()
		}
		if deleteCode == 200 {
			secListUrl = DevConsoleHost + fmt.Sprintf("/api/v1/orgs/1440002/api_keys?public_key=%s", k.PublicKey)
			secListCode, secListData, err = RestyExec("GET", secListUrl, header, "")
			if err != nil {
				secListCode = 0
				secListData = err.Error()
			}
			if secListCode == 200 {
				openApiKeys := &OpenAPIKeys{}
				err := json.Unmarshal([]byte(secListData), openApiKeys)
				if err == nil && len(openApiKeys.Items) == 0 {
					pass = true
				}
			}
		}
	}

	SaveCase("Central_ApiKey", "DeleteOrgApiKey", CaseDetail{
		Url:       deleteUrl,
		Method:    "DELETE",
		ReqHeader: header,
		ReqBody:   "",
		Pass:      pass,
		RspCode:   deleteCode,
		RspData:   deleteData,
		Extra: map[string]interface{}{
			"list_url":      listUrl,
			"list_code":     listCode,
			"list_data":     listData,
			"sec_list_url":  secListUrl,
			"sec_list_code": secListCode,
			"sec_list_data": secListData,
		},
	})
}

func Central_CreateProjectOpenAPIKey() {
	url := DevConsoleHost + "/api/v1/orgs/1440002/projects/3199935/api_keys"

	var header = map[string]string{}
	header["Content-type"] = "application/json"
	header["Authorization"] = consoleAuthorization

	body := `{
			"role": "project:readonly",
			"description": "e2e create console project key"
		}`

	code, data, err := RestyExec("POST", url, header, body)
	if err != nil {
		code = 0
		data = err.Error()
	}

	var listUrl, listData string
	var listCode int
	pass := false
	if code == 200 {
		openApiKey := &OpenAPIKey{}
		err := json.Unmarshal([]byte(data), openApiKey)
		if err == nil && openApiKey.PublicKey != "" && openApiKey.Role == "project:readonly" {
			listUrl = DevConsoleHost + fmt.Sprintf("/api/v1/orgs/1440002/api_keys?public_key=%s", openApiKey.PublicKey)
			listCode, listData, err = RestyExec("GET", listUrl, header, "")
			if err != nil {
				listCode = 0
				listData = err.Error()
			}
			if listCode == 200 {
				openApiKeys := &OpenAPIKeys{}
				err := json.Unmarshal([]byte(listData), openApiKeys)
				if err == nil && len(openApiKeys.Items) == 1 &&
					openApiKeys.Items[0].PublicKey == openApiKey.PublicKey &&
					openApiKeys.Items[0].Role == "org:member" {
					pass = true

				}
			}
		}
	}

	SaveCase("Central_ApiKey", "CreateProjectOpenAPIKey", CaseDetail{
		Url:       url,
		Method:    "POST",
		ReqHeader: header,
		ReqBody:   body,
		Pass:      pass,
		RspCode:   code,
		RspData:   data,
		Extra: map[string]interface{}{
			"list_url":  listUrl,
			"list_code": listCode,
			"list_data": listData,
		},
	})
}

func Central_ListProjectOpenApiKeys() {
	url := DevConsoleHost + "/api/v1/orgs/1440002/projects/3199935/api_keys?page=1&per_page=3"

	var header = map[string]string{}
	header["Content-type"] = "application/json"
	header["Authorization"] = consoleAuthorization

	code, data, err := RestyExec("GET", url, header, "")
	if err != nil {
		code = 0
		data = err.Error()
	}
	pass := false
	if code == 200 {
		keys := &OpenAPIKeys{}
		err := json.Unmarshal([]byte(data), keys)
		if err == nil && len(keys.Items) <= 3 {
			pass = true
			for _, k := range keys.Items {
				if !strings.HasPrefix(k.Role, "project:") {
					pass = false
					break
				}
			}
		}
	}

	SaveCase("Central_ApiKey", "ListProjectOpenApiKeys", CaseDetail{
		Url:       url,
		Method:    "GET",
		ReqHeader: header,
		ReqBody:   "",
		Pass:      pass,
		RspCode:   code,
		RspData:   data,
	})
}

func Central_UpdateProjectApiKey() {
	url := DevConsoleHost + "/api/v1/orgs/1440002/projects/3199935/api_keys?page=1&per_page=3"

	var header = map[string]string{}
	header["Content-type"] = "application/json"
	header["Authorization"] = consoleAuthorization

	code, data, err := RestyExec("GET", url, header, "")
	if err != nil {
		code = 0
		data = err.Error()
	}
	var k *OpenAPIKey
	if code == 200 {
		keys := &OpenAPIKeys{}
		err := json.Unmarshal([]byte(data), keys)
		if err == nil && len(keys.Items) > 0 {
			k = keys.Items[0]
		}
	}

	var updateUrl, updateBody, updateData string
	var updateCode int
	if k != nil {
		updateUrl = DevConsoleHost + fmt.Sprintf("/api/v1/orgs/1440002/projects/3199935/api_keys/%s", k.Id)
		updateBody = `{
			"role": "project:dev",
			"description": "e2e update console project key"
		}`
		updateCode, updateData, err = RestyExec("PATCH", updateUrl, header, updateBody)
		if err != nil {
			updateCode = 0
			updateData = err.Error()
		}
	}

	SaveCase("Central_ApiKey", "UpdateProjectApiKey", CaseDetail{
		Url:       updateUrl,
		Method:    "PATCH",
		ReqHeader: header,
		ReqBody:   updateBody,
		Pass:      updateCode == 200,
		RspCode:   updateCode,
		RspData:   updateData,
		Extra: map[string]interface{}{
			"list_url":  url,
			"list_code": code,
			"list_data": data,
		},
	})

}

func Central_DeleteProjectApiKey() {
	listUrl := DevConsoleHost + "/api/v1/orgs/1440002/projects/3199935/api_keys?page=1&per_page=2"

	var header = map[string]string{}
	header["Content-type"] = "application/json"
	header["Authorization"] = consoleAuthorization

	listCode, listData, err := RestyExec("GET", listUrl, header, "")
	if err != nil {
		listCode = 0
		listData = err.Error()
	}

	var k *OpenAPIKey
	if listCode == 200 {
		openApiKeys := &OpenAPIKeys{}
		err := json.Unmarshal([]byte(listData), openApiKeys)
		if err == nil && len(openApiKeys.Items) > 0 {
			k = openApiKeys.Items[0]
		}
	}

	var deleteUrl, deleteData string
	var deleteCode int
	var secListUrl, secListData string
	var secListCode int
	pass := false
	if k != nil {
		deleteUrl = DevConsoleHost + fmt.Sprintf("/api/v1/orgs/1440002/projects/3199935/api_keys/%s", k.Id)
		deleteCode, deleteData, err = RestyExec("DELETE", deleteUrl, header, "")
		if err != nil {
			deleteCode = 0
			deleteData = err.Error()
		}
		if deleteCode == 200 {
			secListUrl = DevConsoleHost + fmt.Sprintf("/api/v1/orgs/1440002/api_keys?public_key=%s", k.PublicKey)
			secListCode, secListData, err = RestyExec("GET", secListUrl, header, "")
			if err != nil {
				secListCode = 0
				secListData = err.Error()
			}
			if secListCode == 200 {
				openApiKeys := &OpenAPIKeys{}
				err := json.Unmarshal([]byte(secListData), openApiKeys)
				if err == nil && len(openApiKeys.Items) == 0 {
					pass = true
				}
			}
		}
	}

	SaveCase("Central_ApiKey", "DeleteProjectApiKey", CaseDetail{
		Url:       deleteUrl,
		Method:    "DELETE",
		ReqHeader: header,
		ReqBody:   "",
		Pass:      pass,
		RspCode:   deleteCode,
		RspData:   deleteData,
		Extra: map[string]interface{}{
			"list_url":      listUrl,
			"list_code":     listCode,
			"list_data":     listData,
			"sec_list_url":  secListUrl,
			"sec_list_code": secListCode,
			"sec_list_data": secListData,
		},
	})
}

func Central_CreateScimBearerToken() {
	url := DevConsoleHost + "/api/v1/orgs/1440002/bearer-token"
	var header = map[string]string{}
	header["Content-type"] = "application/json"
	header["Authorization"] = consoleAuthorization
	body := fmt.Sprintf(`{
		"description": "e2e-%s"
	}`, CurDateStr())
	code, data, err := RestyExec("POST", url, header, body)
	if err != nil {
		code = 0
		data = err.Error()
	}
	pass := false
	if code == 200 {
		var token = &BearerToken{}
		err := json.Unmarshal([]byte(data), token)
		if err == nil && token.PublicKey != "" && token.SecretKey != "" {
			pass = true
		}
	}
	SaveCase("Central_ApiKey", "CreateScimBearerToken", CaseDetail{
		Url:       url,
		Method:    "POST",
		ReqHeader: header,
		ReqBody:   body,
		Pass:      pass,
		RspCode:   code,
		RspData:   data,
	})
}

type BearerToken struct {
	Id          string `json:"id,omitempty"`
	PublicKey   string `json:"public_key,omitempty"`
	SecretKey   string `json:"secret_key,omitempty"`
	Role        string `json:"role,omitempty"`
	Creator     string `json:"creator,omitempty"`
	Description string `json:"description,omitempty"`
}

type BearerTokens struct {
	Total uint32         `json:"total,omitempty"`
	Items []*BearerToken `json:"items,omitempty"`
}

func Central_ListScimBearerTokens() {
	url := DevConsoleHost + "/api/v1/orgs/1440002/bearer-token?page=1&per_page=2"
	var header = map[string]string{}
	header["Content-type"] = "application/json"
	header["Authorization"] = consoleAuthorization
	code, data, err := RestyExec("GET", url, header, "")
	if err != nil {
		code = 0
		data = err.Error()
	}
	pass := false
	if code == 200 {
		var tokens = &BearerTokens{}
		err := json.Unmarshal([]byte(data), tokens)
		if err == nil && tokens.Total > 0 && len(tokens.Items) <= 2 {
			pass = true
		}
	}
	SaveCase("Central_ApiKey", "ListScimBearerTokens", CaseDetail{
		Url:       url,
		Method:    "GET",
		ReqHeader: header,
		ReqBody:   "",
		Pass:      pass,
		RspCode:   code,
		RspData:   data,
	})
}
