package hub

import (
	"context"
	"errors"
	"testing"
)

// fakeTemp is a TempReader returning a fixed (nullable) value.
type fakeTemp struct{ c *int }

func (f fakeTemp) CPUTempC(context.Context) *int { return f.c }

func intp(v int) *int { return &v }

// HostMetricsNow returns a fresh host block with cpu% from NodeStatus and the temp from the reader.
func TestHostMetricsNow_PopulatesTemp(t *testing.T) {
	px := &fakePx{node: "demo-felhom", ns: newTestNodeStatus()}
	c := NewCollector(px, fakeProber{status: "active"}, nil, nil, nil, nil, "h", "0.14.0", quietLogger()).
		SetTempReader(fakeTemp{c: intp(46)})
	h, err := c.HostMetricsNow(context.Background())
	if err != nil {
		t.Fatalf("HostMetricsNow: %v", err)
	}
	if h.Node != "demo-felhom" || h.CPUPercent != 5 {
		t.Errorf("host = %+v", h)
	}
	if h.CPUTempC == nil || *h.CPUTempC != 46 {
		t.Fatalf("cpu_temp_c = %v, want 46", h.CPUTempC)
	}
	if h.MemoryPercent != 25 {
		t.Errorf("mem%% = %v, want 25", h.MemoryPercent)
	}
}

// A missing temp sensor gracefully nulls cpu_temp_c without failing the host read.
func TestHostMetricsNow_GracefulNullTemp(t *testing.T) {
	px := &fakePx{node: "n", ns: newTestNodeStatus()}
	c := NewCollector(px, fakeProber{status: "active"}, nil, nil, nil, nil, "h", "0.14.0", quietLogger()).
		SetTempReader(fakeTemp{c: nil})
	h, err := c.HostMetricsNow(context.Background())
	if err != nil {
		t.Fatalf("HostMetricsNow: %v", err)
	}
	if h.CPUTempC != nil {
		t.Fatalf("cpu_temp_c = %v, want nil (n/a)", h.CPUTempC)
	}
}

// A NodeStatus failure is a hard error (no useful host view).
func TestHostMetricsNow_NodeStatusErrorIsHard(t *testing.T) {
	px := &fakePx{node: "n", nsErr: errors.New("proxmox down")}
	c := NewCollector(px, fakeProber{status: "active"}, nil, nil, nil, nil, "h", "0.14.0", quietLogger())
	if _, err := c.HostMetricsNow(context.Background()); err == nil {
		t.Fatal("NodeStatus failure must be a hard error")
	}
}

// Collect() (the hub report) also carries the temp now — the operator freebie.
func TestCollect_HostReportCarriesTemp(t *testing.T) {
	px := &fakePx{node: "n", ns: newTestNodeStatus()}
	c := NewCollector(px, fakeProber{status: "active"}, nil, nil, nil, nil, "h", "0.14.0", quietLogger()).
		SetTempReader(fakeTemp{c: intp(51)})
	r, err := c.Collect(context.Background())
	if err != nil {
		t.Fatalf("Collect: %v", err)
	}
	if r.Host.CPUTempC == nil || *r.Host.CPUTempC != 51 {
		t.Fatalf("report host cpu_temp_c = %v, want 51", r.Host.CPUTempC)
	}
}
