package auth

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	domain "github.com/haydenhargreaves/Potion/internal/domain/user"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
)

// GoogleAuthConfig is a global variable that stores the current state of the Google configuration.
// NewGoogleConfig should be called before this value is accessed, or the application will panic
// to prevent a null reference.
var GoogleAuthConfig oauth2.Config

// NewGOogleConfig creates a google authentication configuration. The configuration is set as a
// global variable which can be used by importing this module. The configuration is used to query
// the google OAuth API and collect user data.
//
// This function should be called before any calls to the Google API are made, otherwise a null
// value will be accessed and the call will panic.
//
// The global variable is returned by this function but is not needed.
func NewGoogleConfig(redirectUrl, clientId, clientSecret string, scope []string) oauth2.Config {
	GoogleAuthConfig = oauth2.Config{
		RedirectURL:  redirectUrl,
		ClientID:     clientId,
		ClientSecret: clientSecret,
		Scopes:       scope,
		Endpoint:     google.Endpoint,
	}

	return GoogleAuthConfig
}

// GetUserData accepts a access token and calls the Google OAuth API to receive the respective user
// data. Any errors that occur will be wrapped and returned to the caller.
func GetUserData(accessToken string) (domain.GoogleUserInfo, error) {
	googleApiUrl := fmt.Sprintf("https://www.googleapis.com/oauth2/v2/userinfo?access_token=%s", accessToken)

	resp, err := http.Get(googleApiUrl)
	if err != nil {
		return domain.GoogleUserInfo{}, fmt.Errorf("Failed to fetch user info from Google: %s", err.Error())
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return domain.GoogleUserInfo{}, fmt.Errorf("Failed to read body from response: %s", err.Error())
	}

	var googleUserInfo domain.GoogleUserInfo
	if err := json.Unmarshal(body, &googleUserInfo); err != nil {
		return domain.GoogleUserInfo{}, fmt.Errorf("Failed to parser response: %s", err.Error())
	}

	return googleUserInfo, nil
}
