package login

import (
	"encoding/json"
	"io"
	"net/http"
	"net/url"
	"olympus/oncall/backend/pkg/log"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"
)

type Login struct {
}

func New(g *gin.RouterGroup) (*Login, error) {
	l := &Login{}
	g.GET("/", l.loginHandler())
	return l, nil
}

func (l *Login) loginHandler() func(g *gin.Context) {
	return func(g *gin.Context) {
		code := g.Query("code")

		// get the token using the code in redirect url.
		tokenUrl := viper.GetString("authing.url") + "/oidc/token"
		log.Info("authing url", tokenUrl)
		postData := url.Values{}
		postData.Add("code", code)
		postData.Add("client_id", viper.GetString("authing.client_id"))
		postData.Add("client_secret", viper.GetString("authing.client_secret"))
		postData.Add("grant_type", viper.GetString("authing.grant_type"))
		postData.Add("redirect_uri", viper.GetString("authing.redirect_uri"))

		req, _ := http.NewRequest("POST", tokenUrl, strings.NewReader(postData.Encode()))
		req.Header.Set("User-Agent", "curl")
		req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

		client := http.Client{
			Timeout: 600 * time.Second,
		}
		res, err := client.Do(req)
		if err != nil {
			log.Error("msg", "error: request token using code", "error info", err)
		}
		defer res.Body.Close()
		resBytes, err := io.ReadAll(res.Body)
		if err != nil {
			log.Error("msg", "error: read response to bytes", "error info", err)
		}

		var struct_res TokenResponse
		err = json.Unmarshal(resBytes, &struct_res)
		if err != nil {
			log.Error("msg", "error: unmarshaling bytes to struct", "error info", err)
		}

		params := url.Values{}
		params.Add("id_token", struct_res.Id_token)

		// redirect to frontend after obtaining the token.
		g.Redirect(http.StatusFound, viper.GetString("front_url")+"/shiftview?"+params.Encode())
	}
}
