package webui

import (
	"encoding/json"
	"net/http/httptest"
	"strings"
	"testing"

	"bee/audit/internal/app"
	"bee/audit/internal/platform"
)

func TestXrandrCommandAddsDefaultX11Env(t *testing.T) {
	t.Setenv("DISPLAY", "")
	t.Setenv("XAUTHORITY", "")

	cmd := xrandrCommand("--query")

	var hasDisplay bool
	var hasXAuthority bool
	for _, kv := range cmd.Env {
		if kv == "DISPLAY=:0" {
			hasDisplay = true
		}
		if kv == "XAUTHORITY=/home/bee/.Xauthority" {
			hasXAuthority = true
		}
	}
	if !hasDisplay {
		t.Fatalf("DISPLAY not injected: %v", cmd.Env)
	}
	if !hasXAuthority {
		t.Fatalf("XAUTHORITY not injected: %v", cmd.Env)
	}
}

func TestHandleAPISATRunDecodesBodyWithoutContentLength(t *testing.T) {
	globalQueue.mu.Lock()
	originalTasks := globalQueue.tasks
	globalQueue.tasks = nil
	globalQueue.mu.Unlock()
	t.Cleanup(func() {
		globalQueue.mu.Lock()
		globalQueue.tasks = originalTasks
		globalQueue.mu.Unlock()
	})

	h := &handler{opts: HandlerOptions{App: &app.App{}}}
	req := httptest.NewRequest("POST", "/api/sat/cpu/run", strings.NewReader(`{"profile":"smoke"}`))
	req.ContentLength = -1
	rec := httptest.NewRecorder()

	h.handleAPISATRun("cpu").ServeHTTP(rec, req)

	if rec.Code != 200 {
		t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
	}
	globalQueue.mu.Lock()
	defer globalQueue.mu.Unlock()
	if len(globalQueue.tasks) != 1 {
		t.Fatalf("tasks=%d want 1", len(globalQueue.tasks))
	}
	if got := globalQueue.tasks[0].params.BurnProfile; got != "smoke" {
		t.Fatalf("burn profile=%q want smoke", got)
	}
}

func TestHandleAPIExportBundleQueuesTask(t *testing.T) {
	globalQueue.mu.Lock()
	originalTasks := globalQueue.tasks
	globalQueue.tasks = nil
	globalQueue.mu.Unlock()
	t.Cleanup(func() {
		globalQueue.mu.Lock()
		globalQueue.tasks = originalTasks
		globalQueue.mu.Unlock()
	})

	h := &handler{opts: HandlerOptions{ExportDir: t.TempDir()}}
	req := httptest.NewRequest("POST", "/api/export/bundle", nil)
	rec := httptest.NewRecorder()

	h.handleAPIExportBundle(rec, req)

	if rec.Code != 200 {
		t.Fatalf("status=%d body=%s", rec.Code, rec.Body.String())
	}
	var body map[string]string
	if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil {
		t.Fatalf("decode response: %v", err)
	}
	if body["task_id"] == "" {
		t.Fatalf("missing task_id in response: %v", body)
	}
	globalQueue.mu.Lock()
	defer globalQueue.mu.Unlock()
	if len(globalQueue.tasks) != 1 {
		t.Fatalf("tasks=%d want 1", len(globalQueue.tasks))
	}
	if got := globalQueue.tasks[0].Target; got != "support-bundle" {
		t.Fatalf("target=%q want support-bundle", got)
	}
}

func TestPushFanRingsTracksByNameAndCarriesForwardMissingSamples(t *testing.T) {
	h := &handler{}
	h.pushFanRings([]platform.FanReading{
		{Name: "FAN_A", RPM: 4200},
		{Name: "FAN_B", RPM: 5100},
	})
	h.pushFanRings([]platform.FanReading{
		{Name: "FAN_B", RPM: 5200},
	})

	if len(h.fanNames) != 2 || h.fanNames[0] != "FAN_A" || h.fanNames[1] != "FAN_B" {
		t.Fatalf("fanNames=%v", h.fanNames)
	}
	aVals, _ := h.ringFans[0].snapshot()
	bVals, _ := h.ringFans[1].snapshot()
	if len(aVals) != 2 || len(bVals) != 2 {
		t.Fatalf("fan ring lengths: A=%d B=%d", len(aVals), len(bVals))
	}
	if aVals[1] != 4200 {
		t.Fatalf("FAN_A should carry forward last value, got %v", aVals)
	}
	if bVals[1] != 5200 {
		t.Fatalf("FAN_B should use latest sampled value, got %v", bVals)
	}
}
