package auth0

import (
	"net/http"
	"strconv"

	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
	"github.com/hashicorp/terraform-plugin-sdk/helper/validation"

	"gopkg.in/auth0.v5"
	"gopkg.in/auth0.v5/management"

	v "github.com/alexkappa/terraform-provider-auth0/auth0/internal/validation"
)

func newClient() *schema.Resource {
	return &schema.Resource{

		Create: createClient,
		Read:   readClient,
		Update: updateClient,
		Delete: deleteClient,

		Importer: &schema.ResourceImporter{
			State: schema.ImportStatePassthrough,
		},

		Schema: map[string]*schema.Schema{
			"name": {
				Type:     schema.TypeString,
				Required: true,
			},
			"description": {
				Type:         schema.TypeString,
				Optional:     true,
				ValidateFunc: validation.StringLenBetween(0, 140),
			},
			"client_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"client_secret": {
				Type:      schema.TypeString,
				Computed:  true,
				Sensitive: true,
			},
			"client_secret_rotation_trigger": {
				Type:     schema.TypeMap,
				Optional: true,
			},
			"app_type": {
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: validation.StringInSlice([]string{
					"native", "spa", "regular_web", "non_interactive", "rms",
					"box", "cloudbees", "concur", "dropbox", "mscrm", "echosign",
					"egnyte", "newrelic", "office365", "salesforce", "sentry",
					"sharepoint", "slack", "springcm", "zendesk", "zoom",
				}, false),
			},
			"logo_uri": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"is_first_party": {
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},
			"is_token_endpoint_ip_header_trusted": {
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},
			"oidc_conformant": {
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},
			"callbacks": {
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Optional: true,
			},
			"allowed_logout_urls": {
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Optional: true,
			},
			"grant_types": {
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Computed: true,
				Optional: true,
			},
			"organization_usage": {
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: validation.StringInSlice([]string{
					"deny", "allow", "require",
				}, false),
			},
			"organization_require_behavior": {
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: validation.StringInSlice([]string{
					"no_prompt", "pre_login_prompt",
				}, false),
			},
			"allowed_origins": {
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Optional: true,
			},
			"allowed_clients": {
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Optional: true,
			},
			"web_origins": {
				Type:     schema.TypeList,
				Elem:     &schema.Schema{Type: schema.TypeString},
				Optional: true,
			},
			"jwt_configuration": {
				Type:     schema.TypeList,
				Optional: true,
				Computed: true,
				MaxItems: 1,
				MinItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"lifetime_in_seconds": {
							Type:     schema.TypeInt,
							Optional: true,
							Computed: true,
						},
						"secret_encoded": {
							Type:     schema.TypeBool,
							Optional: true,
							Computed: true,
							ForceNew: true,
						},
						"scopes": {
							Type:     schema.TypeMap,
							Optional: true,
							Elem:     &schema.Schema{Type: schema.TypeString},
						},
						"alg": {
							Type:     schema.TypeString,
							Optional: true,
						},
					},
				},
			},
			"encryption_key": {
				Type:     schema.TypeMap,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"sso": {
				Type:     schema.TypeBool,
				Optional: true,
			},
			"sso_disabled": {
				Type:     schema.TypeBool,
				Optional: true,
			},
			"cross_origin_auth": {
				Type:     schema.TypeBool,
				Optional: true,
			},
			"cross_origin_loc": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"custom_login_page_on": {
				Type:     schema.TypeBool,
				Optional: true,
				Computed: true,
			},
			"custom_login_page": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"form_template": {
				Type:     schema.TypeString,
				Optional: true,
			},
			"addons": {
				Type:     schema.TypeList,
				Optional: true,
				MaxItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"aws": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"azure_blob": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"azure_sb": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"rms": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"mscrm": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"slack": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"sentry": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"box": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"cloudbees": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"concur": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"dropbox": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"echosign": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"egnyte": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"firebase": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"newrelic": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"office365": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"salesforce": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"salesforce_api": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"salesforce_sandbox_api": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"samlp": {
							Type:     schema.TypeList,
							MaxItems: 1,
							Optional: true,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"audience": {
										Type:     schema.TypeString,
										Optional: true,
									},
									"recipient": {
										Type:     schema.TypeString,
										Optional: true,
									},
									"mappings": {
										Type:     schema.TypeMap,
										Optional: true,
										Elem:     schema.TypeString,
									},
									"create_upn_claim": {
										Type:     schema.TypeBool,
										Optional: true,
										Default:  true,
									},
									"passthrough_claims_with_no_mapping": {
										Type:     schema.TypeBool,
										Optional: true,
										Default:  true,
									},
									"map_unknown_claims_as_is": {
										Type:     schema.TypeBool,
										Optional: true,
										Default:  false,
									},
									"map_identities": {
										Type:     schema.TypeBool,
										Optional: true,
										Default:  true,
									},
									"signature_algorithm": {
										Type:     schema.TypeString,
										Optional: true,
										Default:  "rsa-sha1",
									},
									"digest_algorithm": {
										Type:     schema.TypeString,
										Optional: true,
										Default:  "sha1",
									},
									"destination": {
										Type:     schema.TypeString,
										Optional: true,
									},
									"lifetime_in_seconds": {
										Type:     schema.TypeInt,
										Optional: true,
										Default:  3600,
									},
									"sign_response": {
										Type:     schema.TypeBool,
										Optional: true,
									},
									"name_identifier_format": {
										Type:     schema.TypeString,
										Optional: true,
										Default:  "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
									},
									"name_identifier_probes": {
										Type:     schema.TypeList,
										Elem:     &schema.Schema{Type: schema.TypeString},
										Optional: true,
									},
									"authn_context_class_ref": {
										Type:     schema.TypeString,
										Optional: true,
									},
									"typed_attributes": {
										Type:     schema.TypeBool,
										Optional: true,
										Default:  true,
									},
									"include_attribute_name_format": {
										Type:     schema.TypeBool,
										Optional: true,
										Default:  true,
									},
									"logout": {
										Type:     schema.TypeMap,
										Optional: true,
										Elem: &schema.Resource{
											Schema: map[string]*schema.Schema{
												"callback": {
													Type:     schema.TypeString,
													Optional: true,
												},
												"slo_enabled": {
													Type:     schema.TypeBool,
													Optional: true,
												},
											},
										},
									},
									"binding": {
										Type:     schema.TypeString,
										Optional: true,
									},
									"signing_cert": {
										Type:     schema.TypeString,
										Optional: true,
									},
								},
							},
						},
						"layer": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"sap_api": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"sharepoint": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"springcm": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"wams": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"wsfed": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"zendesk": {
							Type:     schema.TypeMap,
							Optional: true,
						},
						"zoom": {
							Type:     schema.TypeMap,
							Optional: true,
						},
					},
				},
			},
			"token_endpoint_auth_method": {
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
				ValidateFunc: validation.StringInSlice([]string{
					"none",
					"client_secret_post",
					"client_secret_basic",
				}, false),
			},
			"client_metadata": {
				Type:     schema.TypeMap,
				Optional: true,
				Elem:     schema.TypeString,
			},
			"mobile": {
				Type:     schema.TypeList,
				Optional: true,
				MaxItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"android": {
							Type:     schema.TypeList,
							Optional: true,
							MaxItems: 1,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"app_package_name": {
										Type:     schema.TypeString,
										Optional: true,
										AtLeastOneOf: []string{
											"mobile.0.android.0.app_package_name",
											"mobile.0.android.0.sha256_cert_fingerprints",
										},
									},
									"sha256_cert_fingerprints": {
										Type:     schema.TypeList,
										Optional: true,
										Elem:     &schema.Schema{Type: schema.TypeString},
										AtLeastOneOf: []string{
											"mobile.0.android.0.app_package_name",
											"mobile.0.android.0.sha256_cert_fingerprints",
										},
									},
								},
							},
						},
						"ios": {
							Type:     schema.TypeList,
							Optional: true,
							MaxItems: 1,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"team_id": {
										Type:     schema.TypeString,
										Optional: true,
										AtLeastOneOf: []string{
											"mobile.0.ios.0.team_id",
											"mobile.0.ios.0.app_bundle_identifier",
										},
									},
									"app_bundle_identifier": {
										Type:     schema.TypeString,
										Optional: true,
										AtLeastOneOf: []string{
											"mobile.0.ios.0.team_id",
											"mobile.0.ios.0.app_bundle_identifier",
										},
									},
								},
							},
						},
					},
				},
			},
			"initiate_login_uri": {
				Type:     schema.TypeString,
				Optional: true,
				ValidateFunc: validation.All(
					validation.IsURLWithScheme([]string{"https"}),
					v.IsURLWithNoFragment,
				),
			},
			"native_social_login": {
				Type:     schema.TypeList,
				Optional: true,
				Computed: true,
				MaxItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"apple": {
							Type:     schema.TypeList,
							Optional: true,
							MaxItems: 1,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"enabled": {
										Type:     schema.TypeBool,
										Optional: true,
									},
								},
							},
						},
						"facebook": {
							Type:     schema.TypeList,
							Optional: true,
							MaxItems: 1,
							Elem: &schema.Resource{
								Schema: map[string]*schema.Schema{
									"enabled": {
										Type:     schema.TypeBool,
										Optional: true,
									},
								},
							},
						},
					},
				},
			},
			"refresh_token": {
				Type:     schema.TypeList,
				Optional: true,
				Computed: true,
				MaxItems: 1,
				MinItems: 1,
				Elem: &schema.Resource{
					Schema: map[string]*schema.Schema{
						"rotation_type": {
							Type:     schema.TypeString,
							Required: true,
							ValidateFunc: validation.StringInSlice([]string{
								"rotating",
								"non-rotating",
							}, false),
						},
						"expiration_type": {
							Type:     schema.TypeString,
							Required: true,
							ValidateFunc: validation.StringInSlice([]string{
								"expiring",
								"non-expiring",
							}, false),
						},
						"leeway": {
							Type:     schema.TypeInt,
							Optional: true,
						},
						"token_lifetime": {
							Type:     schema.TypeInt,
							Optional: true,
						},
						"infinite_token_lifetime": {
							Type:     schema.TypeBool,
							Optional: true,
						},
						"infinite_idle_token_lifetime": {
							Type:     schema.TypeBool,
							Optional: true,
						},
						"idle_token_lifetime": {
							Type:     schema.TypeInt,
							Optional: true,
						},
					},
				},
			},
		},
	}
}

func createClient(d *schema.ResourceData, m interface{}) error {
	c := expandClient(d)
	api := m.(*management.Management)
	if err := api.Client.Create(c); err != nil {
		return err
	}
	d.SetId(auth0.StringValue(c.ClientID))
	return readClient(d, m)
}

func readClient(d *schema.ResourceData, m interface{}) error {
	api := m.(*management.Management)
	c, err := api.Client.Read(d.Id())
	if err != nil {
		if mErr, ok := err.(management.Error); ok {
			if mErr.Status() == http.StatusNotFound {
				d.SetId("")
				return nil
			}
		}
		return err
	}

	d.Set("client_id", c.ClientID)
	d.Set("client_secret", c.ClientSecret)
	d.Set("name", c.Name)
	d.Set("description", c.Description)
	d.Set("app_type", c.AppType)
	d.Set("logo_uri", c.LogoURI)
	d.Set("is_first_party", c.IsFirstParty)
	d.Set("is_token_endpoint_ip_header_trusted", c.IsTokenEndpointIPHeaderTrusted)
	d.Set("oidc_conformant", c.OIDCConformant)
	d.Set("callbacks", c.Callbacks)
	d.Set("allowed_logout_urls", c.AllowedLogoutURLs)
	d.Set("allowed_origins", c.AllowedOrigins)
	d.Set("allowed_clients", c.AllowedClients)
	d.Set("grant_types", c.GrantTypes)
	d.Set("organization_usage", c.OrganizationUsage)
	d.Set("organization_require_behavior", c.OrganizationRequireBehavior)
	d.Set("web_origins", c.WebOrigins)
	d.Set("sso", c.SSO)
	d.Set("sso_disabled", c.SSODisabled)
	d.Set("cross_origin_auth", c.CrossOriginAuth)
	d.Set("cross_origin_loc", c.CrossOriginLocation)
	d.Set("custom_login_page_on", c.CustomLoginPageOn)
	d.Set("custom_login_page", c.CustomLoginPage)
	d.Set("form_template", c.FormTemplate)
	d.Set("token_endpoint_auth_method", c.TokenEndpointAuthMethod)
	d.Set("native_social_login", flattenCustomSocialConfiguration(c.NativeSocialLogin))
	d.Set("jwt_configuration", flattenClientJwtConfiguration(c.JWTConfiguration))
	d.Set("refresh_token", flattenClientRefreshTokenConfiguration(c.RefreshToken))
	d.Set("encryption_key", c.EncryptionKey)
	d.Set("addons", c.Addons)
	d.Set("client_metadata", c.ClientMetadata)
	d.Set("mobile", c.Mobile)
	d.Set("initiate_login_uri", c.InitiateLoginURI)

	return nil
}

func updateClient(d *schema.ResourceData, m interface{}) error {
	c := expandClient(d)
	api := m.(*management.Management)
	if clientHasChange(c) {
		err := api.Client.Update(d.Id(), c)
		if err != nil {
			return err
		}
	}
	d.Partial(true)
	err := rotateClientSecret(d, m)
	if err != nil {
		return err
	}
	d.Partial(false)
	return readClient(d, m)
}

func deleteClient(d *schema.ResourceData, m interface{}) error {
	api := m.(*management.Management)
	err := api.Client.Delete(d.Id())
	if err != nil {
		if mErr, ok := err.(management.Error); ok {
			if mErr.Status() == http.StatusNotFound {
				d.SetId("")
				return nil
			}
		}
	}
	return err
}

func expandClient(d *schema.ResourceData) *management.Client {

	c := &management.Client{
		Name:                           String(d, "name"),
		Description:                    String(d, "description"),
		AppType:                        String(d, "app_type"),
		LogoURI:                        String(d, "logo_uri"),
		IsFirstParty:                   Bool(d, "is_first_party"),
		IsTokenEndpointIPHeaderTrusted: Bool(d, "is_token_endpoint_ip_header_trusted"),
		OIDCConformant:                 Bool(d, "oidc_conformant"),
		Callbacks:                      Slice(d, "callbacks"),
		AllowedLogoutURLs:              Slice(d, "allowed_logout_urls"),
		AllowedOrigins:                 Slice(d, "allowed_origins"),
		AllowedClients:                 Slice(d, "allowed_clients"),
		GrantTypes:                     Slice(d, "grant_types"),
		OrganizationUsage:              String(d, "organization_usage"),
		OrganizationRequireBehavior:    String(d, "organization_require_behavior"),
		WebOrigins:                     Slice(d, "web_origins"),
		SSO:                            Bool(d, "sso"),
		SSODisabled:                    Bool(d, "sso_disabled"),
		CrossOriginAuth:                Bool(d, "cross_origin_auth"),
		CrossOriginLocation:            String(d, "cross_origin_loc"),
		CustomLoginPageOn:              Bool(d, "custom_login_page_on"),
		CustomLoginPage:                String(d, "custom_login_page"),
		FormTemplate:                   String(d, "form_template"),
		TokenEndpointAuthMethod:        String(d, "token_endpoint_auth_method"),
		InitiateLoginURI:               String(d, "initiate_login_uri"),
	}

	List(d, "refresh_token", IsNewResource(), HasChange()).Elem(func(d ResourceData) {
		c.RefreshToken = &management.ClientRefreshToken{
			RotationType:              String(d, "rotation_type"),
			ExpirationType:            String(d, "expiration_type"),
			Leeway:                    Int(d, "leeway"),
			TokenLifetime:             Int(d, "token_lifetime"),
			InfiniteTokenLifetime:     Bool(d, "infinite_token_lifetime"),
			InfiniteIdleTokenLifetime: Bool(d, "infinite_idle_token_lifetime"),
			IdleTokenLifetime:         Int(d, "idle_token_lifetime"),
		}
	})

	List(d, "jwt_configuration").Elem(func(d ResourceData) {
		c.JWTConfiguration = &management.ClientJWTConfiguration{
			LifetimeInSeconds: Int(d, "lifetime_in_seconds"),
			SecretEncoded:     Bool(d, "secret_encoded", IsNewResource()),
			Algorithm:         String(d, "alg"),
			Scopes:            Map(d, "scopes"),
		}
	})

	if m := Map(d, "encryption_key"); m != nil {
		c.EncryptionKey = map[string]string{}
		for k, v := range m {
			c.EncryptionKey[k] = v.(string)
		}
	}

	List(d, "addons").Elem(func(d ResourceData) {

		c.Addons = make(map[string]interface{})

		for _, name := range []string{
			"aws", "azure_blob", "azure_sb", "rms", "mscrm", "slack", "sentry",
			"box", "cloudbees", "concur", "dropbox", "echosign", "egnyte",
			"firebase", "newrelic", "office365", "salesforce", "salesforce_api",
			"salesforce_sandbox_api", "layer", "sap_api", "sharepoint",
			"springcm", "wams", "wsfed", "zendesk", "zoom",
		} {
			_, ok := d.GetOk(name)
			if ok {
				c.Addons[name] = buildClientAddon(Map(d, name))
			}
		}

		List(d, "samlp").Elem(func(d ResourceData) {

			m := make(MapData)

			m.Set("audience", String(d, "audience"))
			m.Set("authnContextClassRef", String(d, "authn_context_class_ref"))
			m.Set("binding", String(d, "binding"))
			m.Set("signingCert", String(d, "signing_cert"))
			m.Set("createUpnClaim", Bool(d, "create_upn_claim"))
			m.Set("destination", String(d, "destination"))
			m.Set("digestAlgorithm", String(d, "digest_algorithm"))
			m.Set("includeAttributeNameFormat", Bool(d, "include_attribute_name_format"))
			m.Set("lifetimeInSeconds", Int(d, "lifetime_in_seconds"))
			m.Set("logout", buildClientAddon(Map(d, "logout")))
			m.Set("mapIdentities", Bool(d, "map_identities"))
			m.Set("mappings", Map(d, "mappings"))
			m.Set("mapUnknownClaimsAsIs", Bool(d, "map_unknown_claims_as_is"))
			m.Set("nameIdentifierFormat", String(d, "name_identifier_format"))
			m.Set("nameIdentifierProbes", Slice(d, "name_identifier_probes"))
			m.Set("passthroughClaimsWithNoMapping", Bool(d, "passthrough_claims_with_no_mapping"))
			m.Set("recipient", String(d, "recipient"))
			m.Set("signatureAlgorithm", String(d, "signature_algorithm"))
			m.Set("signResponse", Bool(d, "sign_response"))
			m.Set("typedAttributes", Bool(d, "typed_attributes"))

			c.Addons["samlp"] = m
		})
	})

	if v, ok := d.GetOk("client_metadata"); ok {
		c.ClientMetadata = make(map[string]string)
		for key, value := range v.(map[string]interface{}) {
			c.ClientMetadata[key] = (value.(string))
		}
	}

	List(d, "native_social_login").Elem(func(d ResourceData) {
		c.NativeSocialLogin = &management.ClientNativeSocialLogin{}

		List(d, "apple").Elem(func(d ResourceData) {
			m := make(MapData)
			m.Set("enabled", Bool(d, "enabled"))

			c.NativeSocialLogin.Apple = m
		})

		List(d, "facebook").Elem(func(d ResourceData) {
			m := make(MapData)
			m.Set("enabled", Bool(d, "enabled"))

			c.NativeSocialLogin.Facebook = m
		})
	})

	List(d, "mobile").Elem(func(d ResourceData) {

		c.Mobile = make(map[string]interface{})

		List(d, "android").Elem(func(d ResourceData) {
			m := make(MapData)
			m.Set("app_package_name", String(d, "app_package_name"))
			m.Set("sha256_cert_fingerprints", Slice(d, "sha256_cert_fingerprints"))

			c.Mobile["android"] = m
		})

		List(d, "ios").Elem(func(d ResourceData) {
			m := make(MapData)
			m.Set("team_id", String(d, "team_id"))
			m.Set("app_bundle_identifier", String(d, "app_bundle_identifier"))

			c.Mobile["ios"] = m
		})
	})

	return c
}

func buildClientAddon(d map[string]interface{}) map[string]interface{} {

	addon := make(map[string]interface{})

	for key, value := range d {

		switch v := value.(type) {

		case string:
			if i, err := strconv.ParseInt(v, 10, 64); err == nil {
				addon[key] = i
			} else if f, err := strconv.ParseFloat(v, 64); err == nil {
				addon[key] = f
			} else if b, err := strconv.ParseBool(v); err == nil {
				addon[key] = b
			} else {
				addon[key] = v
			}

		case map[string]interface{}:
			addon[key] = buildClientAddon(v)

		case []interface{}:
			addon[key] = v

		default:
			addon[key] = v
		}
	}
	return addon
}

func rotateClientSecret(d *schema.ResourceData, m interface{}) error {
	if d.HasChange("client_secret_rotation_trigger") {
		api := m.(*management.Management)
		c, err := api.Client.RotateSecret(d.Id())
		if err != nil {
			return err
		}
		d.Set("client_secret", c.ClientSecret)
	}
	d.SetPartial("client_secret_rotation_trigger")
	return nil
}

func clientHasChange(c *management.Client) bool {
	return c.String() != "{}"
}

func flattenCustomSocialConfiguration(customSocial *management.ClientNativeSocialLogin) []interface{} {
	if customSocial != nil {
		m := make(map[string]interface{})

		if customSocial.Apple != nil {
			m["apple"] = map[string]interface{}{
				"enabled": customSocial.Apple["enabled"],
			}
		}
		if customSocial.Facebook != nil {
			m["facebook"] = map[string]interface{}{
				"enabled": customSocial.Facebook["enabled"],
			}
		}

		return []interface{}{m}
	}

	return nil
}

func flattenClientJwtConfiguration(jwt *management.ClientJWTConfiguration) []interface{} {
	m := make(map[string]interface{})
	if jwt != nil {
		m["lifetime_in_seconds"] = jwt.LifetimeInSeconds
		m["secret_encoded"] = jwt.SecretEncoded
		m["scopes"] = jwt.Scopes
		m["alg"] = jwt.Algorithm
	}
	return []interface{}{m}
}

func flattenClientRefreshTokenConfiguration(refresh_token *management.ClientRefreshToken) []interface{} {
	m := make(map[string]interface{})
	if refresh_token != nil {
		m["rotation_type"] = refresh_token.RotationType
		m["expiration_type"] = refresh_token.ExpirationType
		m["leeway"] = refresh_token.Leeway
		m["token_lifetime"] = refresh_token.TokenLifetime
		m["infinite_token_lifetime"] = refresh_token.InfiniteTokenLifetime
		m["infinite_idle_token_lifetime"] = refresh_token.InfiniteIdleTokenLifetime
		m["idle_token_lifetime"] = refresh_token.IdleTokenLifetime
	}
	return []interface{}{m}
}
