package services

import (
	"bytes"
	"encoding/json"
	"github.com/google/uuid"
	"net/http"
	"runtime"
	"strings"
	"sync"
	"tinyrdm/backend/storage"
)

// google analytics service
type gaService struct {
	measurementID string
	secretKey     string
	clientID      string
}

type GaDataItem struct {
	ClientID string        `json:"client_id"`
	Events   []GaEventItem `json:"events"`
}

type GaEventItem struct {
	Name   string         `json:"name"`
	Params map[string]any `json:"params"`
}

var ga *gaService
var onceGA sync.Once

func GA() *gaService {
	if ga == nil {
		onceGA.Do(func() {
			// get or create an unique user id
			st := storage.NewLocalStore("device.txt")
			uidByte, err := st.Load()
			if err != nil {
				uidByte = []byte(strings.ReplaceAll(uuid.NewString(), "-", ""))
				st.Store(uidByte)
			}

			ga = &gaService{
				clientID: string(uidByte),
			}
		})
	}
	return ga
}

func (a *gaService) SetSecretKey(measurementID, secretKey string) {
	a.measurementID = measurementID
	a.secretKey = secretKey
}

func (a *gaService) isValid() bool {
	return len(a.measurementID) > 0 && len(a.secretKey) > 0
}

func (a *gaService) sendEvent(events ...GaEventItem) error {
	body, err := json.Marshal(GaDataItem{
		ClientID: a.clientID,
		Events:   events,
	})
	if err != nil {
		return err
	}

	//url := "https://www.google-analytics.com/debug/mp/collect"
	url := "https://www.google-analytics.com/mp/collect"
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
	if err != nil {
		return err
	}

	q := req.URL.Query()
	q.Add("measurement_id", a.measurementID)
	q.Add("api_secret", a.secretKey)
	req.URL.RawQuery = q.Encode()

	response, err := http.DefaultClient.Do(req)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	//if dump, err := httputil.DumpResponse(response, true); err == nil {
	//	log.Println(string(dump))
	//}

	return nil
}

// Startup sends application startup event
func (a *gaService) Startup(version string) {
	if !a.isValid() {
		return
	}

	go a.sendEvent(GaEventItem{
		Name: "startup",
		Params: map[string]any{
			"os":      runtime.GOOS,
			"arch":    runtime.GOARCH,
			"version": version,
		},
	})
}