local typedefs = require "kong.db.schema.typedefs"

local function validate_flows(config)
  if config.enable_authorization_code
  or config.enable_implicit_grant
  or config.enable_client_credentials
  or config.enable_password_grant
  then
    return true
  end

  return nil, "at least one of these fields must be true: enable_authorization_code, enable_implicit_grant, enable_client_credentials, enable_password_grant"
end

return {
  name = "oauth2",
  fields = {
    { consumer = typedefs.no_consumer },
    { protocols = typedefs.protocols_http },
    { config = {
        type = "record",
        fields = {
          { scopes = { description = "Describes an array of scope names that will be available to the end user. If `mandatory_scope` is set to `true`, then `scopes` are required.", type = "array", elements = { type = "string" }, }, },
          { mandatory_scope = { description = "An optional boolean value telling the plugin to require at least one `scope` to be authorized by the end user.", type = "boolean", default = false, required = true }, },
          { provision_key = { description = "The unique key the plugin has generated when it has been added to the Service.", type = "string", unique = true, auto = true, required = true, encrypted = true }, }, -- encrypted = true is a Kong Enterprise Exclusive feature. It does nothing in Kong CE
          { token_expiration = { description = "An optional integer value telling the plugin how many seconds a token should last, after which the client will need to refresh the token. Set to `0` to disable the expiration.", type = "number", default = 7200, required = true }, },
          { enable_authorization_code = { description = "An optional boolean value to enable the three-legged Authorization Code flow (RFC 6749 Section 4.1).", type = "boolean", default = false, required = true }, },
          { enable_implicit_grant = { description = "An optional boolean value to enable the Implicit Grant flow which allows to provision a token as a result of the authorization process (RFC 6749 Section 4.2).", type = "boolean", default = false, required = true }, },
          { enable_client_credentials = { description = "An optional boolean value to enable the Client Credentials Grant flow (RFC 6749 Section 4.4).", type = "boolean", default = false, required = true }, },
          { enable_password_grant = { description = "An optional boolean value to enable the Resource Owner Password Credentials Grant flow (RFC 6749 Section 4.3).", type = "boolean", default = false, required = true }, },
          { hide_credentials = { description = "An optional boolean value telling the plugin to show or hide the credential from the upstream service.", type = "boolean", default = false, required = true }, },
          { accept_http_if_already_terminated = { description = "Accepts HTTPs requests that have already been terminated by a proxy or load balancer.", type = "boolean", default = false, required = true }, },
          { anonymous = { description = "An optional string (consumer UUID or username) value to use as an “anonymous” consumer if authentication fails.", type = "string" }, },
          { global_credentials = { description = "An optional boolean value that allows using the same OAuth credentials generated by the plugin with any other service whose OAuth 2.0 plugin configuration also has `config.global_credentials=true`.", type = "boolean", default = false, required = true }, },
          { auth_header_name = { description = "The name of the header that is supposed to carry the access token.", type = "string", default = "authorization" }, },
          { refresh_token_ttl = typedefs.ttl { default = 1209600, required = true }, },
          { reuse_refresh_token = { description = "An optional boolean value that indicates whether an OAuth refresh token is reused when refreshing an access token.", type = "boolean", default = false, required = true }, },
          { pkce = { description = "Specifies a mode of how the Proof Key for Code Exchange (PKCE) should be handled by the plugin.", type = "string", default = "lax", required = false, one_of = { "none", "lax", "strict" } }, },
          { realm = { description = "When authentication fails the plugin sends `WWW-Authenticate` header with `realm` attribute value.", type = "string", required = false }, },
        },
        custom_validator = validate_flows,
        entity_checks = {
          { conditional = {
              if_field = "mandatory_scope",
              if_match = { eq = true },
              then_field = "scopes",
              then_match = { required = true },
          }, },
        },
      },
    },
  },
}

