package collector

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

func TestCRMScraper_HappyPath(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Authorization") != "Bearer tkn" {
			http.Error(w, "unauthorized", http.StatusUnauthorized)
			return
		}
		_ = json.NewEncoder(w).Encode(map[string]any{
			"collected_at": time.Now().UTC().Format(time.RFC3339),
			"version":      "v-test",
			"uptime_sec":   3600,
			"runtime": map[string]any{
				"goroutines":      42,
				"heap_alloc_mb":   100,
				"heap_inuse_mb":   90,
				"gc_pause_p99_ms": 5,
				"num_gc":          10,
			},
			"db_pool": map[string]any{
				"open_conns":       5,
				"in_use":           2,
				"idle":             3,
				"wait_count":       0,
				"wait_duration_ms": 0,
			},
			"http": map[string]any{
				"requests_total":  1234,
				"error_5xx_count": 3,
				"panic_count":     0,
			},
			"outbox": map[string]any{
				"pending":   12,
				"processed": 99,
				"failed":    1,
			},
		})
	}))
	defer srv.Close()

	s := NewCRMScraper(srv.URL, "tkn", 5*time.Second)
	got, err := s.Scrape(context.Background())
	if err != nil {
		t.Fatal(err)
	}
	if got == nil {
		t.Fatal("nil payload")
	}
	if got.Runtime.Goroutines != 42 {
		t.Errorf("goroutines=%d", got.Runtime.Goroutines)
	}
	if got.Outbox.Pending != 12 {
		t.Errorf("pending=%d", got.Outbox.Pending)
	}
	if got.Version != "v-test" {
		t.Errorf("version=%s", got.Version)
	}
	if got.HTTP.RequestsTotal != 1234 {
		t.Errorf("requests_total=%d", got.HTTP.RequestsTotal)
	}
}

func TestCRMScraper_Unauthorized(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "nope", http.StatusUnauthorized)
	}))
	defer srv.Close()
	s := NewCRMScraper(srv.URL, "wrong", time.Second)
	if _, err := s.Scrape(context.Background()); err == nil {
		t.Error("want error on 401")
	}
}

func TestCRMScraper_ServerError(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "boom", http.StatusInternalServerError)
	}))
	defer srv.Close()
	s := NewCRMScraper(srv.URL, "tkn", time.Second)
	if _, err := s.Scrape(context.Background()); err == nil {
		t.Error("want error on 500")
	}
}

func TestCRMScraper_ContextCancel(t *testing.T) {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		time.Sleep(500 * time.Millisecond)
		_, _ = w.Write([]byte(`{}`))
	}))
	defer srv.Close()
	s := NewCRMScraper(srv.URL, "tkn", 5*time.Second)
	ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
	defer cancel()
	if _, err := s.Scrape(ctx); err == nil {
		t.Error("want error on context cancel")
	}
}
