package provider

import (
	"fmt"
	"net/http"
	"os"
	"strings"

	sdk_config "repository.basistech.ru/BASIS/decort-golang-sdk/config"
)

// dynamixProviderConfig helps organize provider validation
type dynamixProviderConfig struct {
	authenticator      string
	oauth2Url          string
	controllerUrl      string
	user               string
	password           string
	bvsUser            string
	bvsPassword        string
	domain             string
	appId              string
	appSecret          string
	jwt                string
	allowUnverifiedSsl bool
	pathConfig         string
	pathToken          string
	timeToRefresh      int64
	token              sdk_config.Token
	cc_client          *http.Client
}

// new sets up default values, values from env and save user provided values for decort provider into decortConfig:
// authenticator, oauth2Url, controllerUrl transformed to lowercase;
// oauth2Url, user, password, bvsUser, bvsPassword, domain, appId, appSecret, jwt uploaded from env if not provided;
// allowUnverifiedSsl default value set as false.
func (d *dynamixProviderConfig) new(config dynamixProviderModel) {
	d.authenticator = strings.ToLower(config.Authenticator.ValueString())

	if config.Oauth2Url.IsNull() {
		d.oauth2Url = os.Getenv("DYNAMIX_OAUTH2_URL")
	} else {
		d.oauth2Url = config.Oauth2Url.ValueString()
	}
	d.oauth2Url = strings.ToLower(d.oauth2Url)

	if config.ControllerUrl.IsNull() {
		d.controllerUrl = os.Getenv("DYNAMIX_CONTROLLER_URL")
	} else {
		d.controllerUrl = strings.ToLower(config.ControllerUrl.ValueString())
	}

	if config.User.IsNull() {
		d.user = os.Getenv("DYNAMIX_USER")
	} else {
		d.user = config.User.ValueString()
	}

	if config.Password.IsNull() {
		d.password = os.Getenv("DYNAMIX_PASSWORD")
	} else {
		d.password = config.Password.ValueString()
	}

	if config.BvsUser.IsNull() {
		d.bvsUser = os.Getenv("DYNAMIX_BVS_USER")
	} else {
		d.bvsUser = config.BvsUser.ValueString()
	}

	if config.BvsPassword.IsNull() {
		d.bvsPassword = os.Getenv("DYNAMIX_BVS_PASSWORD")
	} else {
		d.bvsPassword = config.BvsPassword.ValueString()
	}

	if config.Domain.IsNull() {
		d.domain = os.Getenv("DYNAMIX_DOMAIN")
	} else {
		d.domain = config.Domain.ValueString()
	}

	if config.AppId.IsNull() {
		d.appId = os.Getenv("DYNAMIX_APP_ID")
	} else {
		d.appId = config.AppId.ValueString()
	}

	if config.AppSecret.IsNull() {
		d.appSecret = os.Getenv("DYNAMIX_APP_SECRET")
	} else {
		d.appSecret = config.AppSecret.ValueString()
	}

	if config.Jwt.IsNull() {
		d.jwt = os.Getenv("DYNAMIX_JWT")
	} else {
		d.jwt = config.Jwt.ValueString()
	}

	if config.AllowUnverifiedSsl.IsNull() {
		d.allowUnverifiedSsl = false // default false
	} else {
		d.allowUnverifiedSsl = config.AllowUnverifiedSsl.ValueBool()
	}

	if !config.PathConfig.IsNull() {
		d.pathConfig = config.PathConfig.ValueString()
	}

	if !config.PathToken.IsNull() {
		d.pathToken = config.PathToken.ValueString()
	}

	if !config.TimeToRefresh.IsNull() {
		d.timeToRefresh = config.TimeToRefresh.ValueInt64()
	}

	d.token = sdk_config.Token{}
}

// validateAuthenticator validates authenticator and other parameters from provider configuration provided by user.
// If successful, the mode and nil is returned. If unsuccessful for any
// reason, the method will return mode = MODE_UNDEF and error.
func (d *dynamixProviderConfig) validateAuthenticator() (int, error) {
	var mode = MODE_UNDEF
	if d.oauth2Url == "" {
		return mode, fmt.Errorf("OAuth2 URL is required")
	}
	if d.controllerUrl == "" {
		return mode, fmt.Errorf("controllerURL is required")
	}
	switch d.authenticator {
	case "jwt":
		if d.jwt == "" {
			return mode, fmt.Errorf("authenticator mode 'jwt' specified but no JWT provided")
		}
		mode = MODE_JWT
	case "decs3o":
		if d.appId == "" {
			return mode, fmt.Errorf("authenticator mode 'decs3o' specified but no Application ID provided")
		}
		if d.appSecret == "" {
			return mode, fmt.Errorf("authenticator mode 'decs3o' specified but no Secret ID provided")
		}
		mode = MODE_DECS3O
	case "legacy":
		if d.user == "" {
			return mode, fmt.Errorf("authenticator mode 'legacy' specified but no user provided")
		}
		if d.password == "" {
			return mode, fmt.Errorf("authenticator mode 'legacy' specified but no password provided")
		}
		if d.appId == "" {
			return mode, fmt.Errorf("authenticator mode 'legacy' specified but no Application ID provided")
		}
		if d.appSecret == "" {
			return mode, fmt.Errorf("authenticator mode 'legacy' specified but no Secret ID provided")
		}
		mode = MODE_LEGACY
	case "bvs":
		if d.bvsUser == "" {
			return mode, fmt.Errorf("authenticator mode 'bvs' specified but no bvs user provided")
		}
		if d.bvsPassword == "" {
			return mode, fmt.Errorf("authenticator mode 'bvs' specified but no bvs password provided")
		}
		if d.appId == "" {
			return mode, fmt.Errorf("authenticator mode 'bvs' specified but no Application ID provided")
		}
		if d.appSecret == "" {
			return mode, fmt.Errorf("authenticator mode 'bvs' specified but no Secret ID provided")
		}
		if d.domain == "" {
			return mode, fmt.Errorf("authenticator mode 'bvs' specified but no Domain provided")
		}
		mode = MODE_BVS
	default:
		return mode, fmt.Errorf("unknown authenticator mode %q provided", d.authenticator)
	}

	return mode, nil
}
