package e2e

import (
	"encoding/json"
	"fmt"

	"github.com/duke-git/lancet/v2/slice"
)

func ExecCentralSSOCase() {
	Central_ListOrgActiveAuthMethods()
	Console_UpdateAuthMethod()
	Central_ListAuthMethods()
	Central_SetAuthMethodStatus()
	Central_ShowAuthMethods()
	Central_CheckAuthMethod()
	Central_GetEmailDomains()

}

func Central_ListOrgActiveAuthMethods() {
	url := DevConsoleHost + "/api/v1/auth-method?org_id=1440002"

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

	pass := false
	if code == 200 {
		var rsp = &ListOrgActiveAuthMethodsRsp{}
		err := json.Unmarshal([]byte(data), rsp)
		if err == nil && rsp.OrgId == "1440002" {
			for _, m := range rsp.AuthMethods {
				if m.Name == "google-oauth2" {
					pass = true
					break
				}
			}
		}
	}

	SaveCase("Central_SSO", "ListOrgActiveAuthMethods", CaseDetail{
		Url:       url,
		Method:    "GET",
		ReqHeader: nil,
		ReqBody:   "",
		Pass:      pass,
		RspCode:   code,
		RspData:   data,
	})

}

type ListOrgActiveAuthMethodsRsp struct {
	AuthMethods []*OrgAuthMethod `json:"auth_methods,omitempty"`
	OrgId       string           `json:"org_id,omitempty"`
	OrgName     string           `json:"org_name,omitempty"`
}

type OrgAuthMethod struct {
	Name             string      `json:"name,omitempty"`
	Type             string      `json:"type,omitempty"`
	AllowEmailDomain []string    `json:"allow_email_domain,omitempty"`
	AutoProvision    bool        `json:"auto_provision,omitempty"`
	Status           string      `json:"status,omitempty"`
	DisplayName      string      `json:"display_name,omitempty"`
	OidcConfig       *OidcConfig `json:"oidc_config,omitempty"`
	SamlConfig       *SamlConfig `json:"saml_config,omitempty"`
	ScimProvision    bool        `json:"scim_provision,omitempty"`
}

type OidcConfig struct {
	ClientId     string `json:"client_id,omitempty"`
	ClientSecret string `json:"client_secret,omitempty"`
	IssuerUrl    string `json:"issuer_url,omitempty"`
	ApiToken     string `json:"api_token,omitempty"`
}

type SamlConfig struct {
	MetadataUrl string `json:"metadata_url,omitempty"`
	SignOnUrl   string `json:"sign_on_url,omitempty"`
	SigningCert string `json:"signing_cert,omitempty"`
}

type ListAuthMethodsRsp struct {
	AuthMethods                      []*OrgAuthMethod `json:"auth_methods,omitempty"`
	CallbackUrl                      string           `json:"callback_url,omitempty"`
	SamlPostBackUrl                  string           `json:"saml_post_back_url,omitempty"`
	SamlEntityId                     string           `json:"saml_entity_id,omitempty"`
	ScimConnectorBaseUrl             string           `json:"scim_connector_base_url,omitempty"`
	ScimUniqueIdentifierField        string           `json:"scim_unique_identifier_field,omitempty"`
	ScimSupportedProvisioningActions []string         `json:"scim_supported_provisioning_actions,omitempty"`
}

func Console_UpdateAuthMethod() {
	url := DevConsoleHost + "/api/v1/orgs/1440002/auth-method/update"

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

	body := fmt.Sprintf(`{
		"name": "google-oauth2",
		"type": "Social",
		"allow_email_domain": ["pingcap.com", "%s.com"],
		"auto_provision": true
	}`, CurDateStr())

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

	pass := false
	var listUrl, listData string
	var listCode int
	if code == 200 {
		listUrl = DevConsoleHost + "/api/v1/orgs/1440002/auth-method/list"
		listCode, listData, err = RestyExec("GET", listUrl, header, "")
		if err != nil {
			listCode = 0
			listData = err.Error()
		}
		if listCode == 200 {
			var rsp = &ListAuthMethodsRsp{}
			err := json.Unmarshal([]byte(listData), rsp)
			if err == nil {
				for _, m := range rsp.AuthMethods {
					if m.Name == "google-oauth2" && slice.Contain(m.AllowEmailDomain, "pingcap.com") &&
						slice.Contain(m.AllowEmailDomain, fmt.Sprintf("%s.com", CurDateStr())) {
						pass = true
						break
					}
				}
			}
		}
	}

	SaveCase("Central_SSO", "UpdateAuthMethod", 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_ListAuthMethods() {
	url := DevConsoleHost + "/api/v1/orgs/1440002/auth-method/list?name=google-oauth2"
	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 rsp = &ListAuthMethodsRsp{}
		err := json.Unmarshal([]byte(data), rsp)
		if err == nil && len(rsp.AuthMethods) == 1 && rsp.AuthMethods[0].Name == "google-oauth2" {
			pass = true
		}
	}
	SaveCase("Central_SSO", "ListAuthMethods", CaseDetail{
		Url:       url,
		Method:    "GET",
		ReqHeader: header,
		ReqBody:   "",
		Pass:      pass,
		RspCode:   code,
		RspData:   data,
	})
}

func Central_SetAuthMethodStatus() {
	url := DevConsoleHost + "/api/v1/orgs/1440002/auth-method/status"

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

	body := `{
		"name": "google-oauth2",
		"type": "Social",
		"status": "disable"
	}`

	code, data, err := RestyExec("POST", url, header, body)
	if err != nil {
		code = 0
		data = err.Error()
	}
	var listUrl, listData string
	var listCode int
	var secListUrl, secListData string
	var secListCode int
	var updateUrl, updateData string
	var updateCode int
	var updateBody = `{
		"name": "google-oauth2",
		"type": "Social",
		"status": "enable"
	}`
	pass := false
	if code == 200 {
		listUrl = DevConsoleHost + "/api/v1/auth-method?org_id=1440002"
		listCode, listData, err = RestyExec("GET", listUrl, nil, "")
		if err != nil {
			listCode = 0
			listData = err.Error()
		}

		if listCode == 200 {
			var rsp = &ListOrgActiveAuthMethodsRsp{}
			err := json.Unmarshal([]byte(listData), rsp)
			var findGoogle = false
			if err == nil && rsp.OrgId == "1440002" {
				for _, m := range rsp.AuthMethods {
					if m.Name == "google-oauth2" {
						findGoogle = true
						break
					}
				}
			}
			if !findGoogle {
				updateUrl = DevConsoleHost + "/api/v1/orgs/1440002/auth-method/status"
				updateCode, updateData, err = RestyExec("POST", updateUrl, header, updateBody)
				if err != nil {
					updateCode = 0
					updateData = err.Error()
				}
				if updateCode == 200 {
					secListUrl = DevConsoleHost + "/api/v1/auth-method?org_id=1440002"
					secListCode, secListData, err = RestyExec("GET", secListUrl, nil, "")
					if err != nil {
						secListCode = 0
						secListData = err.Error()
					}
					if secListCode == 200 {
						var rsp = &ListOrgActiveAuthMethodsRsp{}
						err := json.Unmarshal([]byte(secListData), rsp)
						if err == nil && rsp.OrgId == "1440002" {
							for _, m := range rsp.AuthMethods {
								if m.Name == "google-oauth2" {
									pass = true
									break
								}
							}
						}
					}
				}
			}
		}
	}

	SaveCase("Central_SSO", "SetAuthMethodStatus", 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,
			"update_url":    updateUrl,
			"update_code":   updateCode,
			"update_data":   updateData,
			"sec_list_url":  secListUrl,
			"sec_list_code": secListCode,
			"sec_List_data": secListData,
		},
	})

}

func Central_ShowAuthMethods() {
	url := DevConsoleHost + "/api/v1/orgs/1440002/auth-method"
	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 rsp = &ListAuthMethodsRsp{}
		err := json.Unmarshal([]byte(data), rsp)
		if err == nil && len(rsp.AuthMethods) > 0 {
			pass = true
		}
	}
	SaveCase("Central_SSO", "ShowAuthMethods", CaseDetail{
		Url:       url,
		Method:    "GET",
		ReqHeader: header,
		ReqBody:   "",
		Pass:      pass,
		RspCode:   code,
		RspData:   data,
	})
}

func Central_CheckAuthMethod() {
	url := DevConsoleHost + "/api/v1/auth-method/valid-check?name=SAML-1440002"
	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 rsp = &CheckAuthMethodRsp{}
		err := json.Unmarshal([]byte(data), rsp)
		if err == nil && rsp.Valid {
			pass = true
		}
	}
	SaveCase("Central_SSO", "CheckAuthMethod", CaseDetail{
		Url:       url,
		Method:    "GET",
		ReqHeader: header,
		ReqBody:   "",
		Pass:      pass,
		RspCode:   code,
		RspData:   data,
	})
}

type CheckAuthMethodRsp struct {
	Valid bool `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"`
}

func Central_GetEmailDomains() {
	url := DevConsoleHost + "/api/v1/orgs/1440002/auth-method/email-domain"
	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()
	}
	SaveCase("Central_SSO", "GetEmailDomains", CaseDetail{
		Url:       url,
		Method:    "GET",
		ReqHeader: header,
		ReqBody:   "",
		Pass:      code == 200,
		RspCode:   code,
		RspData:   data,
	})
}

type GetEmailDomainsRsp struct {
	EmailDomains []string `protobuf:"bytes,1,rep,name=email_domains,json=emailDomains,proto3" json:"email_domains,omitempty"`
}
