package handlers

import (
	"encoding/json"
	"github.com/statping/statping/types/core"
	"github.com/statping/statping/types/errors"
	"github.com/statping/statping/utils"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	"net/http"
	"strings"
	"time"
)

func googleOAuth(r *http.Request) (*oAuth, error) {
	auth := core.App.OAuth
	code := r.URL.Query().Get("code")

	config := &oauth2.Config{
		ClientID:     auth.GoogleClientID,
		ClientSecret: auth.GoogleClientSecret,
		Endpoint:     google.Endpoint,
		RedirectURL:  core.App.Domain + basePath + "oauth/google",
	}

	gg, err := config.Exchange(r.Context(), code)
	if err != nil {
		return nil, err
	}

	if !gg.Valid() {
		return nil, errors.New("oauth token is not valid")
	}

	info, err := returnGoogleInfo(gg.AccessToken)
	if err != nil {
		return nil, err
	}

	if !validateGoogle(info) {
		return nil, errors.New("google user is not allowed to login")
	}

	return &oAuth{
		Token:    gg,
		Username: info.Name,
		Email:    info.Email,
	}, nil
}

func validateGoogle(info googleUserInfo) bool {
	auth := core.App.OAuth
	if auth.GoogleUsers == "" {
		return true
	}

	if auth.GoogleUsers != "" {
		users := strings.Split(auth.GoogleUsers, ",")
		for _, u := range users {
			if strings.ToLower(info.Email) == strings.ToLower(u) {
				return true
			}
			if strings.ToLower(info.Hd) == strings.ToLower(u) {
				return true
			}
		}
	}

	return false
}

func returnGoogleInfo(token string) (googleUserInfo, error) {
	resp, _, err := utils.HttpRequest("https://www.googleapis.com/oauth2/v1/userinfo?alt=json&access_token="+token, "GET", nil, nil, nil, 10*time.Second, true, nil)
	if err != nil {
		return googleUserInfo{}, err
	}
	var user googleUserInfo
	if err := json.Unmarshal(resp, &user); err != nil {
		return googleUserInfo{}, err
	}
	return user, nil
}

type googleUserInfo struct {
	ID            string `json:"id"`
	Email         string `json:"email"`
	VerifiedEmail bool   `json:"verified_email"`
	Name          string `json:"name"`
	GivenName     string `json:"given_name"`
	FamilyName    string `json:"family_name"`
	Link          string `json:"link"`
	Picture       string `json:"picture"`
	Gender        string `json:"gender"`
	Locale        string `json:"locale"`
	Hd            string `json:"hd"`
}