// Package telemetry handles product telemetry
package telemetry

import (
	"bytes"
	"encoding/json"
	"net/http"
	"sync"
	"time"
)

const (
	telemetryEndpoint = "https://www.google-analytics.com/mp/collect"
	tid               = "G-14J8SY6F0J"
	tk                = "sgPLmshGTPiF-X57rzEIKA"
)

var (
	client     *Client
	clientOnce sync.Once
	httpClient = &http.Client{Timeout: 5 * time.Second}
)

type Client struct {
	enabled        bool
	installationID string
	mu             sync.RWMutex
}

type TradeEvent struct {
	Exchange  string
	TradeType string
	Symbol    string
	AmountUSD float64
	Leverage  int
	UserID    string
	TraderID  string
}

type AIUsageEvent struct {
	UserID        string
	TraderID      string
	ModelProvider string // openai, deepseek, anthropic, etc.
	ModelName     string // gpt-4o, deepseek-chat, claude-3, etc.
	Channel       string // payment channel: "claw402" or "native"
	InputTokens   int
	OutputTokens  int
}

type telemetryPayload struct {
	ClientID string           `json:"client_id"`
	Events   []telemetryEvent `json:"events"`
}

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

func Init(enabled bool, installationID string) {
	clientOnce.Do(func() {
		client = &Client{
			enabled:        enabled,
			installationID: installationID,
		}
	})
}

func SetInstallationID(id string) {
	if client == nil {
		return
	}
	client.mu.Lock()
	defer client.mu.Unlock()
	client.installationID = id
}

func GetInstallationID() string {
	if client == nil {
		return ""
	}
	client.mu.RLock()
	defer client.mu.RUnlock()
	return client.installationID
}

func SetEnabled(enabled bool) {
	if client == nil {
		return
	}
	client.mu.Lock()
	defer client.mu.Unlock()
	client.enabled = enabled
}

func IsEnabled() bool {
	if client == nil {
		return false
	}
	client.mu.RLock()
	defer client.mu.RUnlock()
	return client.enabled
}

func TrackTrade(event TradeEvent) {
	if client == nil || !IsEnabled() {
		return
	}

	// Send asynchronously to not block trading
	go func() {
		_ = sendTradeEvent(event)
	}()
}

// sendTradeEvent sends the trade event to GA4
func sendTradeEvent(event TradeEvent) error {
	client.mu.RLock()
	installationID := client.installationID
	client.mu.RUnlock()

	payload := telemetryPayload{
		ClientID: installationID,
		Events: []telemetryEvent{
			{
				Name: "trade",
				Params: map[string]interface{}{
					"exchange":             event.Exchange,
					"trade_type":           event.TradeType,
					"symbol":               event.Symbol,
					"amount_usd":           event.AmountUSD,
					"leverage":             event.Leverage,
					"installation_id":      installationID, // For counting active installations
					"user_id":              event.UserID,   // For counting active users
					"trader_id":            event.TraderID, // For counting active traders
					"engagement_time_msec": 1,              // Required by GA4
				},
			},
		},
	}

	jsonData, err := json.Marshal(payload)
	if err != nil {
		return err
	}

	url := telemetryEndpoint + "?measurement_id=" + tid + "&api_secret=" + tk
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")

	resp, err := httpClient.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	return nil
}

func TrackStartup(version string) {
	if client == nil || !IsEnabled() {
		return
	}

	go func() {
		client.mu.RLock()
		installationID := client.installationID
		client.mu.RUnlock()

		payload := telemetryPayload{
			ClientID: installationID,
			Events: []telemetryEvent{
				{
					Name: "app_startup",
					Params: map[string]interface{}{
						"version":              version,
						"installation_id":      installationID,
						"engagement_time_msec": 1,
					},
				},
			},
		}

		jsonData, _ := json.Marshal(payload)
		url := telemetryEndpoint + "?measurement_id=" + tid + "&api_secret=" + tk
		req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
		if req != nil {
			req.Header.Set("Content-Type", "application/json")
			resp, err := httpClient.Do(req)
			if err == nil {
				resp.Body.Close()
			}
		}
	}()
}

func TrackAIUsage(event AIUsageEvent) {
	if client == nil || !IsEnabled() {
		return
	}

	go func() {
		client.mu.RLock()
		installationID := client.installationID
		client.mu.RUnlock()

		payload := telemetryPayload{
			ClientID: installationID,
			Events: []telemetryEvent{
				{
					Name: "ai_usage",
					Params: map[string]interface{}{
						"model_provider":       event.ModelProvider,
						"model_name":           event.ModelName,
						"channel":              event.Channel,
						"input_tokens":         event.InputTokens,
						"output_tokens":        event.OutputTokens,
						"total_tokens":         event.InputTokens + event.OutputTokens,
						"installation_id":      installationID,
						"user_id":              event.UserID,
						"trader_id":            event.TraderID,
						"engagement_time_msec": 1,
					},
				},
			},
		}

		jsonData, _ := json.Marshal(payload)
		url := telemetryEndpoint + "?measurement_id=" + tid + "&api_secret=" + tk
		req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
		if req != nil {
			req.Header.Set("Content-Type", "application/json")
			resp, err := httpClient.Do(req)
			if err == nil {
				resp.Body.Close()
			}
		}
	}()
}
