package main

import (
	"encoding/base64"
	"encoding/json"
	"flag"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"reflect"
	"strconv"
	"strings"

	log "github.com/sirupsen/logrus"
)

var (
	httpPort            = flag.Int("http_port", LookupEnvOrInt("HTTP_PORT", 80), "HTTP port to serve on (defaults to 80)")
	logLevel            = flag.String("loglevel", LookupEnvOrString("LOGLEVEL", "debug"), "log level (debug, info, warning, error) (defaults to debug)")
	cozyDomain          = flag.String("cozy_domain", LookupEnvOrString("COZY_DOMAIN", "cozy.self-data.alpha.grandlyon.com"), "Cozy domain (defaults to cozy.self-data.alpha.grandlyon.com)")
	cozyRedirectURI     = flag.String("cozy_redirect_uri", LookupEnvOrString("COZY_REDIRECT_URI", "/accounts/enedisgrandlyon/redirect"), "Cozy redirect URI (defaults to /accounts/enedisgrandlyon/redirect)")
	cozyGrdfRedirectURI = flag.String("cozy_grdf_redirect_uri", LookupEnvOrString("COZY_GRDF_REDIRECT_URI", "/accounts/grdfgrandlyon/redirect"), "Cozy redirect URI (defaults to /accounts/grdfgrandlyon/redirect)")
	cozyProxyURI        = flag.String("cozy_proxy_uri", LookupEnvOrString("COZY_PROXY_URI", "https://oauth-proxy.self-data.alpha.grandlyon.com"), "Cozy domain (defaults to https://oauth-proxy.self-data.alpha.grandlyon.com)")
)

type EnedisTokenResponse struct {
	AccessToken          string `json:"access_token"`
	TokenType            string `json:"token_type"`
	ExpiresIn            int    `json:"expires_in"`
	RefreshToken         string `json:"refresh_token"`
	Scope                string `json:"scope"`
	RefreshTokenIssuedAt string `json:"refresh_token_issued_at"`
	IssueAt              string `json:"issued_at"`
	UsagePointId         string `json:"usage_points_id"`
}

type GrdfConsentement []struct {
	Pce             string `json:"pce"`
	IdAccreditation string `json:"id_accreditation"`
}

type GrdfConsentementToken struct {
	AtHash          string `json:"at_hash"`
	Sub             string `json:"sub"`
	AuditTrackingId string `json:"auditTrackingId"`
	Iss             string `json:"iss"`
	TokenName       string `json:"tokenName"`
	Aud             string `json:"aud"`
	CHash           string `json:"c_hash"`
	Acr             string `json:"acr"`
	Azp             string `json:"azp"`
	AuthYime        int    `json:"auth_time"`
	Realm           string `json:"realm"`
	Consentements   string `json:"consentements"`
	Exp             int    `json:"exp"`
	TokenType       string `json:"tokenType"`
	Iat             int    `json:"iat"`
}

type GrdfTokenResponse struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	IdToken      string `json:"id_token"`
	TokenType    string `json:"token_type"`
	ExpiresIn    int    `json:"expires_in"`
	Scope        string `json:"scope"`
	Pce          string `json:"pce"`
}

func LookupEnvOrString(key string, defaultVal string) string {
	if val, ok := os.LookupEnv(key); ok {
		return val
	}
	return defaultVal
}

func LookupEnvOrInt(key string, defaultVal int) int {
	if val, ok := os.LookupEnv(key); ok {
		v, err := strconv.Atoi(val)
		if err != nil {
			log.Fatalf("LookupEnvOrInt[%s]: %v", key, err)
		}
		return v
	}
	return defaultVal
}

func findItem(arrayType interface{}, item interface{}) bool {
	arr := reflect.ValueOf(arrayType)
	if arr.Kind() != reflect.Array {
		panic("Invalid data-type")
	}
	for i := 0; i < arr.Len(); i++ {
		if arr.Index(i).Interface() == item {
			return true
		}
	}

	return false
}

func logRoute(key string) {
	// format is : Subject - action - location - description
	switch key {
	case "Ping_enedis_new_auth":
		log.Debug("Enedis - Received - Authorize - new /auth request from Cozy")
	case "Ping_enedis_redirect":
		log.Debug("Enedis - Received - Redirect")
	case "Ping_enedis_new_token":
		log.Debug("Enedis - Received - Token - new /token request from Cozy")
	case "Ping_enedis_oauth_token":
		log.Debug("Enedis - Received - Token - an oauth token request from Cozy")
	case "Ping_enedis_refresh":
		log.Debug("Enedis - Received - Token - a refresh token request from Cozy")

	case "Ping_grdf_new_auth":
		log.Debug("Grdf - Received - Authorize - new /auth request from Cozy")
	case "Ping_grdf_redirect":
		log.Debug("Grdf - Received - Redirect")
	case "Ping_grdf_new_token":
		log.Debug("Grdf - Received - Token - new /token request from Cozy")

	case "Enedis_success_oauth":
		log.Debug("Enedis - Success - Oauth - oauth dance successfully done")
	case "Enedis_success_token":
		log.Debug("Enedis - Success - Token - Enedis gave a new token or refresh token to the cozy stack")
	case "Grdf_success":
		log.Debug("Grdf - Success - Oauth - oauth dance successfully done")
	case "Grdf_success_token":
		log.Debug("Grdf - Success - Token - Grdf gave a new token to the cozy stack")

	case "Enedis_error":
		log.Error("Enedis - Error - Oauth - something wrong happened with enedis")
	case "Enedis_redirect_error":
		log.Error("Enedis - Error - Redirect - an error occured with enedis redirection")
	case "Enedis_token_error":
		log.Error("Enedis - Error - Token - an error occured with enedis /token endpoint")

	case "Grdf_error":
		log.Error("Grdf - Error - Oauth - something wrong happened with grdf")
	case "Grdf_redirect_error":
		log.Error("Grdf - Error - Redirect - an error occured with grdf redirection")
	case "Grdf_token_error":
		log.Error("Grdf - Error - Token - an error occured with grdf /token endpoint")

	case "Proxy_error":
		log.Error("Proxy - Error - Oauth - something wrong happened in the proxy")

	case "Proxy_error_enedis_auth":
		log.Error("Proxy - Error - Enedis - Authorize")
	case "Proxy_error_grdf_auth":
		log.Error("Proxy - Error - Grdf - Authorize")

	case "Proxy_error_enedis_redirect":
		log.Error("Proxy - Error - Enedis - Redirect")
	case "Proxy_error_grdf_redirect":
		log.Error("Proxy - Error - Grdf - Redirect")

	case "Proxy_error_enedis_token":
		log.Error("Proxy - Error - Enedis - Token")
	case "Proxy_error_grdf_token":
		log.Error("Proxy - Error - Grdf - Token")

	case "Cozy_error_enedis_auth":
		log.Error("Cozy - Error - Enedis - Authorize")
	case "Cozy_error_grdf_auth":
		log.Error("Cozy - Error - Grdf - Authorize")

	default:
		log.Debug("logRoute was called with unknown arguments")
	}
}

func main() {
	// Parse the flags
	flag.Parse()

	// Init logging
	log.SetOutput(os.Stdout)
	log.SetFormatter(&log.TextFormatter{
		PadLevelText:     true,
		ForceQuote:       true,
		DisableTimestamp: false,
		FullTimestamp:    true,
		TimestampFormat:  "2006-01-02 15:04:05",
	})

	// Configure log level
	switch strings.ToLower(*logLevel) {
	case "error":
		log.SetLevel(log.ErrorLevel)
	case "warning":
		log.SetLevel(log.WarnLevel)
	case "info":
		log.SetLevel(log.InfoLevel)
	case "debug":
		log.SetLevel(log.DebugLevel)
	default:
		log.SetLevel(log.DebugLevel)
		log.Fatalf("Unknown logging level %s. Choose between debug, info, warning or error.", *logLevel)
	}

	mux := http.NewServeMux()
	log.Infof("Starting Server on port %d\n", *httpPort)

	mux.HandleFunc("/healthcheck", func(w http.ResponseWriter, r *http.Request) {
		io.WriteString(w, "OK\n")
	})

	// ENEDIS AUTH ENDPOINT
	mux.HandleFunc("/auth", func(w http.ResponseWriter, r *http.Request) {
		logRoute("Ping_enedis_new_auth")
		query := r.URL.Query()
		log.Debug("WL - EnedisReceived - Authorize - Query received from Cozy: ", query)

		clientId := query.Get("client_id")
		state := query.Get("state")
		responseType := "code"
		// here we use the redirect_uri param to transmit our stack url
		// We keep only the instance name to not reach the 100 max char of redirectUrl
		cozyOrigin := query.Get("redirect_uri")
		if len(clientId) > 0 && len(state) > 0 && len(cozyOrigin) > 0 {
			splitIndexStart := strings.Index(cozyOrigin, ":")
			splitIndexEnd := strings.Index(cozyOrigin, ".")
			if splitIndexStart > -1 && splitIndexEnd > -1 {
				instanceName := cozyOrigin[splitIndexStart+3 : splitIndexEnd]
				// DEV API
				// authURL := "https://gw.hml.api.enedis.fr/dataconnect/v1/oauth2/authorize"
				// PROD API
				authURL := "https://mon-compte-particulier.enedis.fr/dataconnect/v1/oauth2/authorize"
				redirectUrl := authURL + "?client_id=" + clientId + "&duration=P6M&response_type=" + responseType + "&state=" + state + "-" + instanceName

				log.Info("WL - EnedisSuccess - Authorize - Redirecting user to Enedis: ", redirectUrl)
				http.Redirect(w, r, redirectUrl, 302)
			} else {
				logRoute("Proxy_error_enedis_auth")
				log.Error("WL - ProxyError - Enedis - Authorize - redirect_uri bad format from Cozy " + cozyOrigin)
				http.Error(w, http.StatusText(500), 500)
			}
		} else {
			logRoute("Cozy_error_enedis_auth")
			log.Debug("WL - CozyError - Enedis - Authorize - Missing parameters in request")
			http.Error(w, http.StatusText(500), 500)
		}
	})

	// GRDF ADICT AUTHORIZE ENDPOINT
	mux.HandleFunc("/grdf_authorize", func(w http.ResponseWriter, r *http.Request) {
		logRoute("Ping_grdf_new_auth")
		query := r.URL.Query()
		log.Debug("WL - GrdfReceived - Authorize - Query received: ", query)

		clientId := query.Get("client_id")
		state := query.Get("state")
		cozyOrigin := query.Get("redirect_uri")
		if len(clientId) > 0 && len(state) > 0 && len(cozyOrigin) > 0 {
			splitIndexStart := strings.Index(cozyOrigin, ":")
			splitIndexEnd := strings.Index(cozyOrigin, ".")
			if splitIndexStart > -1 && splitIndexEnd > -1 {
				instanceName := cozyOrigin[splitIndexStart+3 : splitIndexEnd]
				redirectProxy := *cozyProxyURI + "/redirect-grdf"
				authURL := "https://sofit-sso-oidc.grdf.fr/openam/oauth2/realms/externeGrdf/authorize"

				redirectUrl := authURL + "?client_id=" + clientId + "&scope=openid&response_type=code&redirect_uri=" + redirectProxy + "&login_hint=Prénom|Nom||Ecolyo&state=" + state + "-" + instanceName

				log.Info("WL - GrdfSuccess - Authorize - Redirect user to: ", redirectUrl)
				http.Redirect(w, r, redirectUrl, 302)
			} else {
				logRoute("Proxy_error_grdf_auth")
				log.Error("WL - ProxyError - Grdf - Authorize - redirect_uri bad format from Cozy " + cozyOrigin)
				http.Error(w, http.StatusText(500), 500)
			}
		} else {
			logRoute("Cozy_error_grdf_auth")
			log.Debug("WL - CozyError - Grdf - Authorize - Missing parameters in request")
			http.Error(w, http.StatusText(500), 500)
		}
	})

	//ENEDIS REDIRECT ENDPOINT
	mux.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
		logRoute("Ping_enedis_redirect")
		query := r.URL.Query()
		log.Debug("WL - EnedisReceived - Redirect - Query received: ", query)

		code := query.Get("code")
		req_state := query.Get("state")
		statusCodes := [4]string{"400", "403", "500", "503"}

		if len(code) > 0 && len(req_state) > 0 {
			if findItem(statusCodes, code) {
				intCode, err := strconv.Atoi(code)
				if err != nil {
					logRoute("Proxy_error_enedis_redirect")
					log.Error("WL - ProxyError - Enedis - Redirect - String to int convert error for status code: ", err)
					http.Error(w, http.StatusText(500), 500)
					return
				}
				logRoute("Enedis_redirect_error")
				log.Error("WL - EnedisError - Redirect - status code error: ", code)
				http.Error(w, http.StatusText(intCode), intCode)
				return
			}

			splitIndex := strings.Index(req_state, "-")
			if splitIndex == -1 {
				logRoute("Proxy_error_enedis_redirect")
				log.Error("WL - ProxyError - Enedis - Redirect - No host found in query")
				http.Error(w, http.StatusText(500), 500)
				return
			}
			state := req_state[0:splitIndex]
			host := req_state[splitIndex+1:]
			usagePointId := query.Get("usage_point_id")
			cozyURL := "https://" + host + "." + *cozyDomain + *cozyRedirectURI
			redir := cozyURL + "?code=" + code + "&state=" + state + "&usage_point_id=" + usagePointId
			log.Info("WL - EnedisSuccess - Redirect - Redirecting user to  Cozy stack: ", redir)
			http.Redirect(w, r, redir, 302)
		} else {
			logRoute("Proxy_error_enedis_redirect")
			log.Error("WL - ProxyError - Enedis - Redirect - Missing parameters in request")
			http.Error(w, http.StatusText(500), 500)
		}
	})

	//ENEDIS WRONG REDIRECT ENDPOINT
	mux.HandleFunc("/redirect/", func(w http.ResponseWriter, r *http.Request) {
		logRoute("Enedis_redirect_error")
		log.Error("WL - EnedisError - Redirect - Wrong route received from Enedis ")
		http.Error(w, http.StatusText(500), 500)
	})

	//GRDF REDIRECT ENDPOINT
	mux.HandleFunc("/redirect-grdf", func(w http.ResponseWriter, r *http.Request) {
		logRoute("Ping_grdf_redirect")
		query := r.URL.Query()
		log.Debug("WL - GrdfReceived - Redirect - Received redirect answer from GRDF: ", query)

		code := query.Get("code")
		req_state := query.Get("state")

		if len(code) > 0 && len(req_state) > 0 {
			splitIndex := strings.Index(req_state, "-")
			if splitIndex == -1 {
				logRoute("Proxy_error_grdf_redirect")
				log.Error("WL - ProxyError - Grdf - Redirect - No host found")
				http.Error(w, http.StatusText(500), 500)
				return
			}
			state := req_state[0:splitIndex]
			host := req_state[splitIndex+1:]

			cozyURL := "https://" + host + "." + *cozyDomain + *cozyGrdfRedirectURI

			redir := cozyURL + "?code=" + code + "&state=" + state
			log.Info("WL - GrdfSuccess - Redirect - Redirect to Cozy stack: ", redir)
			http.Redirect(w, r, redir, 302)
		} else {
			logRoute("Proxy_error_grdf_redirect")
			log.Error("WL - ProxyError - Grdf - Redirect - Missing parameters in request")
			http.Error(w, http.StatusText(500), 500)
		}
	})

	//ENEDIS TOKEN ENDPOINT
	mux.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) {
		logRoute("Ping_enedis_new_token")
		query := r.URL.Query()
		log.Debug("WL - EnedisReceived - Token - Received new token request from Cozy: ", query)

		clientId := ""
		clientSecret := ""
		code := ""
		grantType := ""
		refreshToken := ""

		// For request token params are into query parameters
		if len(query) == 0 {
			log.Debug("WL - EnedisInfo - Token - No params found in url query, trying to catch them from body")
			contents, err := ioutil.ReadAll(r.Body)
			if err != nil {
				logRoute("Proxy_error_enedis_token")
				log.Error("WL - ProxyError - Enedis - Token - Unable to read the body: ", err)
				http.Error(w, err.Error(), 500)
				return
			}
			params, err := url.ParseQuery(string(contents))
			if err != nil {
				logRoute("Proxy_error_enedis_token")
				log.Error("WL - ProxyError - Enedis - Token - Unable to parse query", err)
				http.Error(w, err.Error(), 500)
				return
			}
			if val, ok := params["client_id"]; ok {
				clientId = val[0]
			}
			if val, ok := params["client_secret"]; ok {
				clientSecret = val[0]
			}
			if val, ok := params["code"]; ok {
				code = val[0]
			}
			if val, ok := params["grant_type"]; ok {
				grantType = val[0]
			}
			if val, ok := params["refresh_token"]; ok {
				refreshToken = val[0]
			}
		} else {
			// Retrieve params from query
			clientId = query.Get("client_id")
			clientSecret = query.Get("client_secret")
			code = query.Get("code")
			grantType = query.Get("grant_type")
			refreshToken = query.Get("refresh_token")
		}
		// Print out the result
		log.WithFields(log.Fields{
			"client_id":     clientId,
			"client_secret": clientSecret,
			"code":          code,
			"grant_type":    grantType,
			"refresh_token": refreshToken,
		}).Debug("WL - EnedisInfo - Token - Result")

		// DEV API
		// tokenUrl := "https://gw.hml.api.enedis.fr/v1/oauth2/token"
		// PROD API
		tokenUrl := "https://gw.prd.api.enedis.fr/v1/oauth2/token"

		data := url.Values{}
		data.Set("client_id", clientId)
		data.Set("client_secret", clientSecret)
		data.Set("code", code)
		data.Set("grant_type", grantType)
		if refreshToken != "" {
			logRoute("Ping_enedis_refresh")
			log.Debug("WL - EnedisReceived - Token - Cozystack asks for a new refresh token")
			data.Set("refresh_token", refreshToken)
			data.Set("grant_type", "refresh_token")
		} else {
			logRoute("Ping_enedis_oauth_token")
			log.Debug("WL - EnedisReceived - Token - Cozystack asks for a regular token to end the oauth dance")
		}

		log.Debug("WL - EnedisInfo - Token - Send request to Enedis token endpoint: ", tokenUrl)
		response, err := http.PostForm(tokenUrl, data)
		if err != nil {
			logRoute("Proxy_error_enedis_token")
			log.Error("WL - ProxyError - Enedis - Token - Unable to post the request: ", err)
			http.Error(w, http.StatusText(500), 500)
			return
		}
		log.Debug("WL - EnedisInfo - Token - Enedis answered back with status ", response.Status)
		defer response.Body.Close()
		if response.StatusCode >= 200 && response.StatusCode <= 299 {
			// Set Content-Type in response header
			w.Header().Add("Content-Type", "application/json")
			// Decode response Body using the defined type "TokenResponse"
			data := EnedisTokenResponse{}
			decodeError := json.NewDecoder(response.Body).Decode(&data)
			if decodeError != nil {
				logRoute("Proxy_error_enedis_token")
				log.Error("WL - ProxyError - Enedis - Token - Unable to decode data: ", decodeError)
				http.Error(w, decodeError.Error(), 500)
				return
			}
			// Response with json data
			jsonError := json.NewEncoder(w).Encode(data)
			if jsonError != nil {
				logRoute("Proxy_error_enedis_token")
				log.Error("WL - ProxyError - Enedis - Token - Unable to encode data: ", jsonError)
				http.Error(w, jsonError.Error(), 500)
				return
			}
			if refreshToken != "" {
				logRoute("Enedis_success_token")
			} else {
				logRoute("Enedis_success_oauth")
			}
			log.Info("WL - EnedisSuccess - Token - Respond correctly to Cozy stack")
		} else {
			logRoute("Enedis_token_error")
			log.Error("WL - EnedisError - Token - Enedis answer back with status code: ", response.StatusCode)
			http.Error(w, http.StatusText(response.StatusCode), response.StatusCode)
		}
	})

	//GRDF TOKEN ENDPOINT
	mux.HandleFunc("/grdf_token", func(w http.ResponseWriter, r *http.Request) {
		logRoute("Ping_grdf_new_token")
		query := r.URL.Query()
		log.Debug("WL - GrdfReceived - Token - Received new token request from Cozy", query)

		clientId := ""
		clientSecret := ""
		code := ""
		grantType := ""
		scope := ""
		redirectUri := *cozyProxyURI + "/redirect-grdf"
		pce := ""
		IdToken := ""

		// For request token params are into query parameters
		if len(query) == 0 {
			log.Debug("WL - GrdfInfo - Token - No params found in url query \nStack probably asks for a refresh token \nTrying to catch them from body")
			contents, err := ioutil.ReadAll(r.Body)
			if err != nil {
				logRoute("Proxy_error_grdf_token")
				log.Error("WL - ProxyError - Grdf - Token - Unable to read the body: ", err)
				http.Error(w, err.Error(), 500)
				return
			}
			params, err := url.ParseQuery(string(contents))
			if err != nil {
				logRoute("Proxy_error_grdf_token")
				log.Error("WL - ProxyError - Grdf - Token - Unable to parse the query: ", err)
				http.Error(w, err.Error(), 500)
				return
			}
			if val, ok := params["client_id"]; ok {
				clientId = val[0]
			}
			if val, ok := params["client_secret"]; ok {
				clientSecret = val[0]
			}
			if val, ok := params["grant_type"]; ok {
				grantType = val[0]
			}
		} else {
			// Retrieve params from query
			clientId = query.Get("client_id")
			clientSecret = query.Get("client_secret")
			code = query.Get("code")
			grantType = query.Get("grant_type")
		}

		// Print out the result
		log.WithFields(log.Fields{
			"client_id":     clientId,
			"client_secret": clientSecret,
			"code":          code,
			"grant_type":    grantType,
			"redirect_uri":  redirectUri,
			"scope":         scope,
		}).Debug("WL - GrdfInfo - Token - Result")

		tokenUrl := "https://sofit-sso-oidc.grdf.fr/openam/oauth2/realms/externeGrdf/access_token"

		if grantType != "refresh_token" {
			// Call GRDF access_token endpoint with code & grant_type = "authorization_code"
			data := url.Values{}
			data.Set("client_id", clientId)
			data.Set("client_secret", clientSecret)
			data.Set("grant_type", "authorization_code")
			data.Set("redirect_uri", redirectUri)
			data.Set("code", code)

			log.Debug("WL - GrdfInfo - Token - data sent is: ", data)
			log.Debug("WL - GrdfInfo - Token - Send request to access_token endpoint with authorization_code: ", tokenUrl)
			response, err := http.PostForm(tokenUrl, data)
			if err != nil {
				logRoute("Proxy_error_grdf_token")
				log.Error("WL - ProxyError - Grdf - Token - Unable to post the request: ", err)
				http.Error(w, http.StatusText(500), 500)
				return
			}
			log.Debug("WL - GrdfInfo - Token - GRDF Endpoint response with status ", response.Status)
			defer response.Body.Close()
			if response.StatusCode >= 200 && response.StatusCode <= 299 {
				// Decode response Body using the defined type "GrdfTokenResponse"
				data := GrdfTokenResponse{}
				decodeError := json.NewDecoder(response.Body).Decode(&data)
				if decodeError != nil {
					logRoute("Proxy_error_grdf_token")
					log.Error("WL - ProxyError - Grdf - Token - Unable to decode data: ", err)
					http.Error(w, decodeError.Error(), 500)
					return
				}
				// Check if IdToken exist
				// Decode the token and retrieve the pce from it
				if len(data.IdToken) > 0 {
					IdToken = data.IdToken
					s := strings.Split(IdToken, ".")
					if len(s[1]) > 0 {
						payload, _ := base64.StdEncoding.DecodeString(s[1])
						// Check if the payload is well ended
						if payload[len(payload)-1] != 125 {
							payload = append(payload, []byte{125}...)
						}
						log.Debug("WL - GrdfInfo - Token - token decoded payload: ", string(payload))
						// Decode the payload from the token
						var token GrdfConsentementToken
						err := json.Unmarshal(payload, &token)
						if err != nil {
							logRoute("Proxy_error_grdf_token")
							log.Error("WL - ProxyError - Grdf - Token - Unable to unmarshal payload from token: ", err)
							http.Error(w, err.Error(), 500)
							return
						}
						log.Debug("WL - GrdfInfo - Token - Consentements found: ", token.Consentements)
						// Decode the consentement information
						if len(token.Consentements) > 0 {
							var consentements GrdfConsentement
							err2 := json.Unmarshal([]byte(token.Consentements), &consentements)
							if err2 != nil {
								logRoute("Proxy_error_grdf_token")
								log.Error("WL - ProxyError - Grdf - Token - Unable to unmarshal consentement information: ", err2)
								http.Error(w, err2.Error(), 500)
								return
							}
							if len(consentements[0].Pce) > 0 {
								pce = consentements[0].Pce
							}
						}
					}
				}
				if len(pce) <= 0 {
					logRoute("Proxy_error_grdf_token")
					log.Error("WL - ProxyError - Grdf - Token - No PCE found")
					http.Error(w, http.StatusText(500), 500)
					return
				}
			} else {
				logRoute("Grdf_token_error")
				log.Error("WL - GrdfError - Token - GRDF response with status code: ", response.StatusCode)
				http.Error(w, http.StatusText(response.StatusCode), response.StatusCode)
				return
			}
		}

		// Call GRDF access_token endpoint with scope & grant_type = "client_credentials"
		data2 := url.Values{}
		data2.Set("client_id", clientId)
		data2.Set("client_secret", clientSecret)
		data2.Set("grant_type", "client_credentials")
		data2.Set("redirect_uri", redirectUri)
		data2.Set("scope", "/adict/v1")

		log.Debug("WL - GrdfInfo - Token - data sent is: ", data2)
		log.Debug("WL - GrdfInfo - Token - send request to access_token endpoint with client_credentials: ", tokenUrl)
		response2, err2 := http.PostForm(tokenUrl, data2)
		if err2 != nil {
			logRoute("Proxy_error_grdf_token")
			log.Error("WL - ProxyError - Grdf - Token - Unable to post the request: ", err2)
			http.Error(w, http.StatusText(500), 500)
			return
		}
		log.Debug("WL - GrdfInfo - Token - Endpoint response with status ", response2.Status)
		defer response2.Body.Close()
		if response2.StatusCode >= 200 && response2.StatusCode <= 299 {
			// Set Content-Type in response header
			w.Header().Add("Content-Type", "application/json")
			// Decode response Body using the defined type "GrdfTokenResponse"
			data := GrdfTokenResponse{}
			decodeError := json.NewDecoder(response2.Body).Decode(&data)
			if decodeError != nil {
				logRoute("Proxy_error_grdf_token")
				log.Error("WL - ProxyError - Grdf - Token - Unable to decode data: ", decodeError)
				http.Error(w, decodeError.Error(), 500)
				return
			}
			if grantType != "refresh_token" {
				data.RefreshToken = "-"
				data.Pce = pce
				data.IdToken = IdToken
			}

			jsonError := json.NewEncoder(w).Encode(data)
			if jsonError != nil {
				logRoute("Proxy_error_grdf_token")
				log.Error("WL - ProxyError - Grdf - Token - Unable to encode data: ", jsonError)
				http.Error(w, jsonError.Error(), 500)
				return
			}
			logRoute("Grdf_success_token")
			log.Info("WL - GrdfSuccess - Token - Response correctly to Cozy stack")
		} else {
			logRoute("Grdf_token_error")
			log.Error("WL - GrdfError - Token - GRDF response with status code: ", response2.StatusCode)
			http.Error(w, http.StatusText(response2.StatusCode), response2.StatusCode)
		}
	})

	log.Fatal(http.ListenAndServe(":"+strconv.Itoa(*httpPort), mux))
}