package api

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

	"crypto-miner-server/internal/db"
	"crypto-miner-server/internal/models"
)

func TestAgentBeaconFleetSecretAuth(t *testing.T) {
	resetAuthState(t)
	const secret = "beacon-test-secret"
	SetAgentPathSecret(secret)

	database, err := db.New(t.TempDir())
	if err != nil {
		t.Fatal(err)
	}
	defer database.Close()

	hub := NewWSHub(database)
	hub.SetFleetSecret(secret)

	body, _ := json.Marshal(map[string]interface{}{
		"agent_id": "agent-beacon-1",
		"stats": map[string]interface{}{
			"hashrate_15s": 100.0,
			"hashrate_1m":  100.0,
			"hashrate_15m": 100.0,
		},
	})

	h := basicAuthMiddleware(http.HandlerFunc(hub.HandleAgentBeacon))
	req := httptest.NewRequest(http.MethodPost, "/api/v1/agent/beacon", bytes.NewReader(body))
	rec := httptest.NewRecorder()
	h.ServeHTTP(rec, req)
	if rec.Code != http.StatusForbidden {
		t.Fatalf("missing secret: got %d", rec.Code)
	}

	req.Header.Set("X-Fleet-Secret", secret)
	rec = httptest.NewRecorder()
	h.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("valid secret: got %d body=%s", rec.Code, rec.Body.String())
	}
	var resp beaconResponse
	if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
		t.Fatal(err)
	}
	if !resp.OK {
		t.Fatal("expected ok")
	}
}

func TestBeaconCommandQueueRoundtrip(t *testing.T) {
	database, err := db.New(t.TempDir())
	if err != nil {
		t.Fatal(err)
	}
	defer database.Close()
	_ = database.UpsertAgent(&models.Agent{ID: "q-agent", Name: "host", Status: "offline"})

	hub := NewWSHub(database)
	hub.MarkBeaconSeen("q-agent")
	if !hub.EnqueueBeaconCommand("q-agent", "pause", nil) {
		t.Fatal("enqueue failed")
	}
	cmds := hub.dequeueBeaconCommands("q-agent")
	if len(cmds) != 1 || cmds[0].Action != "pause" {
		t.Fatalf("commands: %+v", cmds)
	}
	if len(hub.dequeueBeaconCommands("q-agent")) != 0 {
		t.Fatal("queue should be empty")
	}
}

func TestAgentBeaconReturnsQueuedCommands(t *testing.T) {
	resetAuthState(t)
	const secret = "beacon-cmd-secret"
	SetAgentPathSecret(secret)

	database, err := db.New(t.TempDir())
	if err != nil {
		t.Fatal(err)
	}
	defer database.Close()
	_ = database.UpsertAgent(&models.Agent{ID: "cmd-agent", Name: "pc", Status: "offline"})

	hub := NewWSHub(database)
	hub.MarkBeaconSeen("cmd-agent")
	_ = hub.EnqueueBeaconCommand("cmd-agent", "resume", nil)

	body, _ := json.Marshal(map[string]string{"agent_id": "cmd-agent"})
	h := basicAuthMiddleware(http.HandlerFunc(hub.HandleAgentBeacon))
	req := httptest.NewRequest(http.MethodPost, "/api/v1/agent/beacon", bytes.NewReader(body))
	req.Header.Set("X-Fleet-Secret", secret)
	rec := httptest.NewRecorder()
	h.ServeHTTP(rec, req)
	if rec.Code != http.StatusOK {
		t.Fatalf("beacon: %d %s", rec.Code, rec.Body.String())
	}
	var resp beaconResponse
	if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
		t.Fatal(err)
	}
	if len(resp.Commands) != 1 || resp.Commands[0].Action != "resume" {
		t.Fatalf("commands: %+v", resp.Commands)
	}
}
