package lib

import (
	"encoding/json"
	"io"
	"net/http"
	"net/http/httptest"
	"sync"
	"testing"
	"time"
)

func TestCollectPayload(t *testing.T) {
	cfg := TelemetryConfig{
		FreqSeconds: 60,
		Host:        "http://localhost:9999",
		Token:       "test-token",
		DataDir:     t.TempDir(),
		Mode:        "self-hosted",
	}
	startTime := time.Now().Add(-5 * time.Minute)

	payload := CollectPayload(cfg, startTime)

	if payload.Version == "" {
		t.Error("version should not be empty")
	}
	if payload.Hostname == "" {
		t.Error("hostname should not be empty")
	}
	if payload.UptimeSeconds < 299 {
		t.Errorf("uptime should be ~300s, got %d", payload.UptimeSeconds)
	}
	if payload.Timestamp == "" {
		t.Error("timestamp should not be empty")
	}
	if payload.Mode != "self-hosted" {
		t.Errorf("mode should be self-hosted, got %s", payload.Mode)
	}
	if payload.System.OS == "" {
		t.Error("OS should not be empty")
	}
	if payload.System.CPUs < 1 {
		t.Errorf("CPUs should be >= 1, got %d", payload.System.CPUs)
	}
	if payload.System.MemTotalMB <= 0 {
		t.Errorf("memory total should be > 0, got %d", payload.System.MemTotalMB)
	}

	// Verify JSON roundtrip.
	data, err := json.Marshal(payload)
	if err != nil {
		t.Fatalf("marshal: %v", err)
	}
	var decoded TelemetryPayload
	if err := json.Unmarshal(data, &decoded); err != nil {
		t.Fatalf("unmarshal: %v", err)
	}
	if decoded.Hostname != payload.Hostname {
		t.Errorf("hostname mismatch after roundtrip")
	}
}

func TestPostTelemetry(t *testing.T) {
	var mu sync.Mutex
	var received TelemetryPayload
	var authHeader string

	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		mu.Lock()
		defer mu.Unlock()
		authHeader = r.Header.Get("Authorization")
		body, _ := io.ReadAll(r.Body)
		json.Unmarshal(body, &received)
		w.WriteHeader(http.StatusOK)
	}))
	defer server.Close()

	cfg := TelemetryConfig{
		FreqSeconds: 1,
		Host:        server.URL,
		Token:       "secret-token",
		DataDir:     t.TempDir(),
		Mode:        "hosted",
	}

	StartTelemetry(cfg)

	// Wait for the first post.
	time.Sleep(500 * time.Millisecond)

	mu.Lock()
	defer mu.Unlock()

	if authHeader != "Bearer secret-token" {
		t.Errorf("expected Bearer secret-token, got %q", authHeader)
	}
	if received.Mode != "hosted" {
		t.Errorf("expected mode=hosted, got %q", received.Mode)
	}
	if received.Version == "" {
		t.Error("version should not be empty")
	}
}

// Verify that StartTelemetry does nothing when disabled.
func TestTelemetryDisabled(t *testing.T) {
	// Should not panic or start goroutines.
	StartTelemetry(TelemetryConfig{})
	StartTelemetry(TelemetryConfig{FreqSeconds: 0, Host: "http://example.com"})
	StartTelemetry(TelemetryConfig{FreqSeconds: 60, Host: ""})
}
