package main

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

	wruntime "github.com/wailsapp/wails/v2/pkg/runtime"
)


type LauncherAuth struct {
	Id string
	Name string
	token string
}

type McProfile struct {
	Id string
	Name string
}

type devcodeResp struct {
	User_code string
	Device_code string
	Verification_url string
	Expires_in string
	Interval int
	Message string
}

type authenticationResp struct {
	Access_token string
	Token_type string
	Refresh_token string
	Expires_in string
	Error string
	Error_description string
}

type xboxAuthProperties struct {
	AuthMethod string
	SiteName string
	RpsTicket string
}

type xboxAuthRequest struct {
	Properties xboxAuthProperties
	RelyingParty string
	TokenType string
}

type xboxDisplayClaim struct {
	Uhs string
	Gtg string
	Xid string
	Agg string
	Usr string
	Utr string
	Prv string
}

type xboxDisplayClaims struct {
	Xui []xboxDisplayClaim
}

type xboxAuthResponse struct {
	IssueInstant time.Time
	NotAfter time.Time
	Token string
	DisplayClaims xboxDisplayClaims
}

type XSTSProperties struct {
	SandboxId string
	UserTokens []string
}

type XSTSRequest struct {
	Properties XSTSProperties
	RelyingParty string
	TokenType string
}

type McAuthRequest struct {
	Xtoken string `json:"xtoken"`
	Platform string `json:"platform"`
}

type McAuthResponse struct {
	Username string
	Access_token string
	Expires_in string
	Token_type string
}

func AuthCode(a App) (authenticationResp, error) {
	authentication := authenticationResp{}
	resp, err := http.PostForm("https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode", url.Values{
		"client_id": {client_id},
		"scope": {"XboxLive.SignIn XboxLive.offline_access"},
	})
	if err != nil {
		return authentication, fmt.Errorf("Unable to request device code: %e\n", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return authentication, fmt.Errorf("Unable to request device code: %s\n", resp.Status)
	}
	data, _ := io.ReadAll(resp.Body)
	codeResp := devcodeResp{}
	json.Unmarshal(data, &codeResp)
	//display message
	wruntime.MessageDialog(a.Ctx, wruntime.MessageDialogOptions{Type: wruntime.InfoDialog, Title: "Authentication", Message: codeResp.Message})
	ticker := time.NewTicker(time.Second * time.Duration(codeResp.Interval))
	for range ticker.C {
		resp, err := http.PostForm("https://login.microsoftonline.com/consumers/oauth2/v2.0/token", url.Values{
		"client_id": {client_id},
		"grant_type": {"urn:ietf:params:oauth:grant-type:device_code"},
		"device_code": {codeResp.Device_code},
		})
		if err != nil {
			return authentication, fmt.Errorf("Authentication request error %e\n", err)
		}
		defer resp.Body.Close()
		data, _ := io.ReadAll(resp.Body)
		json.Unmarshal(data, &authentication)
		if authentication.Error == "" {
			return authentication, nil
		}
	}
	return authentication, fmt.Errorf("Unknown error")
}

func TokenRefresh(app App, auth authenticationResp) (authenticationResp, error) {
	resp, err := http.PostForm("https://login.microsoftonline.com/consumers/oauth2/v2.0/token", url.Values{
	"client_id": {client_id},
	"grant_type": {"refresh_token"},
	"refresh_token": {auth.Refresh_token},
	"scope": {"XboxLive.SignIn XboxLive.offline_access"},
	})
	if err != nil {
		return authenticationResp{}, fmt.Errorf("unable to request refresh token: %e\n", err)
	}
	defer resp.Body.Close()
	data, _ := io.ReadAll(resp.Body)
	authResp := authenticationResp{}
	json.Unmarshal(data, &authResp)
	return authResp, nil
}
