package collector

import (
	"bee/audit/internal/schema"
	"fmt"
	"testing"
)

func TestParseSFPDOM(t *testing.T) {
	raw := `
	Module temperature                        :  41.23 C
	Module voltage                            :  3.30 V
	Laser bias current                        :  6.12 mA
	Laser output power                        :  0.4712 mW / -3.27 dBm
	Receiver signal average optical power     :  0.4123 mW / -3.85 dBm
`
	got := parseSFPDOM(raw)

	if v, ok := got["sfp_temperature_c"].(float64); !ok || v != 41.23 {
		t.Fatalf("sfp_temperature_c mismatch: %#v", got["sfp_temperature_c"])
	}
	if v, ok := got["sfp_voltage_v"].(float64); !ok || v != 3.30 {
		t.Fatalf("sfp_voltage_v mismatch: %#v", got["sfp_voltage_v"])
	}
	if v, ok := got["sfp_bias_ma"].(float64); !ok || v != 6.12 {
		t.Fatalf("sfp_bias_ma mismatch: %#v", got["sfp_bias_ma"])
	}
	if v, ok := got["sfp_tx_power_dbm"].(float64); !ok || v != -3.27 {
		t.Fatalf("sfp_tx_power_dbm mismatch: %#v", got["sfp_tx_power_dbm"])
	}
	if v, ok := got["sfp_rx_power_dbm"].(float64); !ok || v != -3.85 {
		t.Fatalf("sfp_rx_power_dbm mismatch: %#v", got["sfp_rx_power_dbm"])
	}
}

func TestParseLSPCIDetailSerial(t *testing.T) {
	raw := `
05:00.0 Ethernet controller: Mellanox Technologies MT28908 Family [ConnectX-6]
	Serial number: NIC-SN-12345
`
	if got := parseLSPCIDetailSerial(raw); got != "NIC-SN-12345" {
		t.Fatalf("serial=%q want %q", got, "NIC-SN-12345")
	}
}

func TestParsePCIVPDSerial(t *testing.T) {
	raw := []byte{0x82, 0x05, 0x00, 'M', 'L', 'X', '5', 0x90, 0x08, 0x00, 'S', 'N', 0x08, 'M', 'T', '1', '2', '3', '4', '5', '6'}
	if got := parsePCIVPDSerial(raw); got != "MT123456" {
		t.Fatalf("serial=%q want %q", got, "MT123456")
	}
}

func TestEnrichPCIeWithNICTelemetryAddsSerialFallback(t *testing.T) {
	origDetail := queryPCILSPCIDetail
	origVPD := readPCIVPDFile
	origIfaces := netIfacesByBDF
	origReadMAC := readNetAddressFile
	origEth := ethtoolInfoQuery
	origModule := ethtoolModuleQuery
	origCarrier := readNetCarrierFile
	t.Cleanup(func() {
		queryPCILSPCIDetail = origDetail
		readPCIVPDFile = origVPD
		netIfacesByBDF = origIfaces
		readNetAddressFile = origReadMAC
		ethtoolInfoQuery = origEth
		ethtoolModuleQuery = origModule
		readNetCarrierFile = origCarrier
	})

	queryPCILSPCIDetail = func(bdf string) (string, error) {
		if bdf != "0000:18:00.0" {
			t.Fatalf("unexpected bdf: %s", bdf)
		}
		return "Serial number: NIC-SN-98765\n", nil
	}
	readPCIVPDFile = func(string) ([]byte, error) {
		return nil, fmt.Errorf("no vpd needed")
	}
	netIfacesByBDF = func(string) []string { return []string{"eth0"} }
	readNetAddressFile = func(iface string) (string, error) {
		if iface != "eth0" {
			t.Fatalf("unexpected iface: %s", iface)
		}
		return "aa:bb:cc:dd:ee:ff", nil
	}
	readNetCarrierFile = func(string) (string, error) { return "1", nil }
	ethtoolInfoQuery = func(string) (string, error) { return "", fmt.Errorf("skip firmware") }
	ethtoolModuleQuery = func(string) (string, error) { return "", fmt.Errorf("skip optics") }

	class := "EthernetController"
	bdf := "0000:18:00.0"
	devs := []schema.HardwarePCIeDevice{{
		DeviceClass: &class,
		BDF:         &bdf,
	}}

	out := enrichPCIeWithNICTelemetry(devs)
	if out[0].SerialNumber == nil || *out[0].SerialNumber != "NIC-SN-98765" {
		t.Fatalf("serial=%v want NIC-SN-98765", out[0].SerialNumber)
	}
	if len(out[0].MacAddresses) != 1 || out[0].MacAddresses[0] != "aa:bb:cc:dd:ee:ff" {
		t.Fatalf("mac_addresses=%v", out[0].MacAddresses)
	}
}

func TestEnrichPCIeWithNICTelemetrySkipsModuleQueryWithoutCarrier(t *testing.T) {
	origIfaces := netIfacesByBDF
	origReadMAC := readNetAddressFile
	origEth := ethtoolInfoQuery
	origModule := ethtoolModuleQuery
	origCarrier := readNetCarrierFile
	t.Cleanup(func() {
		netIfacesByBDF = origIfaces
		readNetAddressFile = origReadMAC
		ethtoolInfoQuery = origEth
		ethtoolModuleQuery = origModule
		readNetCarrierFile = origCarrier
	})

	netIfacesByBDF = func(string) []string { return []string{"eth0"} }
	readNetAddressFile = func(string) (string, error) { return "aa:bb:cc:dd:ee:ff", nil }
	readNetCarrierFile = func(string) (string, error) { return "0", nil }
	ethtoolInfoQuery = func(string) (string, error) { return "", fmt.Errorf("skip firmware") }
	ethtoolModuleQuery = func(string) (string, error) { return "", fmt.Errorf("no module") }

	class := "EthernetController"
	bdf := "0000:18:00.0"
	devs := []schema.HardwarePCIeDevice{{
		DeviceClass: &class,
		BDF:         &bdf,
	}}

	out := enrichPCIeWithNICTelemetry(devs)
	if len(out[0].MacAddresses) != 1 || out[0].MacAddresses[0] != "aa:bb:cc:dd:ee:ff" {
		t.Fatalf("mac_addresses=%v", out[0].MacAddresses)
	}
}

func TestDBMValue(t *testing.T) {
	tests := []struct {
		in   string
		want float64
		ok   bool
	}{
		{"0.4123 mW / -3.85 dBm", -3.85, true},
		{"-1.23 dBm", -1.23, true},
		{"not supported", 0, false},
	}
	for _, tt := range tests {
		got, ok := dbmValue(tt.in)
		if ok != tt.ok {
			t.Fatalf("dbmValue(%q) ok=%v want %v", tt.in, ok, tt.ok)
		}
		if ok && got != tt.want {
			t.Fatalf("dbmValue(%q)=%v want %v", tt.in, got, tt.want)
		}
	}
}
