package collector

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

func TestParseSASIrcuControllerIDs(t *testing.T) {
	raw := `LSI Corporation SAS2 IR Configuration Utility.
Adapter List
==============
0      SAS2008(B2)
1      SAS2308_2(D1)
`
	ids := parseSASIrcuControllerIDs(raw)
	if len(ids) != 2 || ids[0] != 0 || ids[1] != 1 {
		t.Fatalf("unexpected ids: %#v", ids)
	}
}

func TestParseSASIrcuDisplay(t *testing.T) {
	raw := `Device is a Hard disk
  Enclosure #                         : 32
  Slot #                              : 7
  State                               : Onln
  Size (in MB)/(in sectors)           : 953869/1953525168
  Model Number                        : ST1000NM0033
  Serial No                           : Z1D12345
  Protocol                            : SAS
  Drive Type                          : HDD

Device is a Enclosure services device
  Enclosure #                         : 32
`
	drives := parseSASIrcuDisplay(raw)
	if len(drives) != 1 {
		t.Fatalf("expected 1 drive, got %d", len(drives))
	}
	d := drives[0]
	if d.Slot == nil || *d.Slot != "32:7" {
		t.Fatalf("slot: %v", d.Slot)
	}
	if d.SerialNumber == nil || *d.SerialNumber != "Z1D12345" {
		t.Fatalf("serial: %v", d.SerialNumber)
	}
	if d.Interface == nil || *d.Interface != "SAS" {
		t.Fatalf("interface: %v", d.Interface)
	}
	if d.Status == nil || *d.Status != "OK" {
		t.Fatalf("status: %v", d.Status)
	}
}

func TestParseArcconfPhysicalDrives(t *testing.T) {
	raw := `Device #0
Reported Location      : Channel 0, Device 3
Model                  : Micron_5300
Serial number          : ARC12345
State                  : Online
Total Size             : 894 GB
Transfer Speed         : SATA 6.0Gb/s
SSD                    : Yes
`
	drives := parseArcconfPhysicalDrives(raw)
	if len(drives) != 1 {
		t.Fatalf("expected 1 drive, got %d", len(drives))
	}
	d := drives[0]
	if d.Type == nil || *d.Type != "SSD" {
		t.Fatalf("type: %v", d.Type)
	}
	if d.Interface == nil || *d.Interface != "SATA" {
		t.Fatalf("interface: %v", d.Interface)
	}
	if d.Status == nil || *d.Status != "OK" {
		t.Fatalf("status: %v", d.Status)
	}
}

func TestParseSSACLIPhysicalDrives(t *testing.T) {
	raw := `physicaldrive 1I:1:1 (894 GB, SAS HDD, OK)
   Serial Number: SSACLI001
   Model: MB8000JVYZQ

physicaldrive 1I:1:2 (894 GB, SAS HDD, Failed)
   Serial Number: SSACLI002
   Model: MB8000JVYZQ
`
	drives := parseSSACLIPhysicalDrives(raw)
	if len(drives) != 2 {
		t.Fatalf("expected 2 drives, got %d", len(drives))
	}
	if drives[0].Status == nil || *drives[0].Status != "OK" {
		t.Fatalf("drive0 status: %v", drives[0].Status)
	}
	if drives[1].Status == nil || *drives[1].Status != statusCritical {
		t.Fatalf("drive1 status: %v", drives[1].Status)
	}
}

func TestParseStorcliControllerTelemetry(t *testing.T) {
	raw := []byte(`{
  "Controllers": [
    {
      "Response Data": {
        "BBU_Info": {
          "State of Health": "98 %",
          "Relative State of Charge": "76 %",
          "Temperature": "41 C",
          "Voltage": "12.3 V",
          "Replacement required": "No"
        }
      }
    }
  ]
}`)
	got := parseStorcliControllerTelemetry(raw)
	if len(got) != 1 {
		t.Fatalf("len(got)=%d want 1", len(got))
	}
	if got[0].BatteryHealthPct == nil || *got[0].BatteryHealthPct != 98 {
		t.Fatalf("battery health=%v", got[0].BatteryHealthPct)
	}
	if got[0].BatteryChargePct == nil || *got[0].BatteryChargePct != 76 {
		t.Fatalf("battery charge=%v", got[0].BatteryChargePct)
	}
	if got[0].BatteryTemperatureC == nil || *got[0].BatteryTemperatureC != 41 {
		t.Fatalf("battery temperature=%v", got[0].BatteryTemperatureC)
	}
	if got[0].BatteryVoltageV == nil || *got[0].BatteryVoltageV != 12.3 {
		t.Fatalf("battery voltage=%v", got[0].BatteryVoltageV)
	}
	if got[0].BatteryReplaceRequired == nil || *got[0].BatteryReplaceRequired {
		t.Fatalf("battery replace=%v", got[0].BatteryReplaceRequired)
	}
}

func TestParseSSACLIControllerTelemetry(t *testing.T) {
	raw := `Smart Array P440ar in Slot 0
   Battery/Capacitor Count: 1
   Capacitor Temperature  (C): 37
   Capacitor Charge (%): 94
   Capacitor Health (%): 96
   Capacitor Voltage (V): 9.8
   Capacitor Failed: No
`
	got := parseSSACLIControllerTelemetry(raw)
	if len(got) != 1 {
		t.Fatalf("len(got)=%d want 1", len(got))
	}
	if got[0].BatteryTemperatureC == nil || *got[0].BatteryTemperatureC != 37 {
		t.Fatalf("battery temperature=%v", got[0].BatteryTemperatureC)
	}
	if got[0].BatteryChargePct == nil || *got[0].BatteryChargePct != 94 {
		t.Fatalf("battery charge=%v", got[0].BatteryChargePct)
	}
}

func TestEnrichPCIeWithRAIDTelemetry(t *testing.T) {
	orig := raidToolQuery
	t.Cleanup(func() { raidToolQuery = orig })
	raidToolQuery = func(name string, args ...string) ([]byte, error) {
		switch name {
		case "storcli64":
			return []byte(`{
  "Controllers": [
    {
      "Response Data": {
        "CV_Info": {
          "State of Health": "99 %",
          "Relative State of Charge": "81 %",
          "Temperature": "38 C",
          "Voltage": "12.1 V",
          "Replacement required": "No"
        }
      }
    }
  ]
}`), nil
		default:
			return nil, errors.New("skip")
		}
	}

	vendor := vendorBroadcomLSI
	class := "MassStorageController"
	status := statusOK
	devs := []schema.HardwarePCIeDevice{{
		VendorID:                &vendor,
		DeviceClass:             &class,
		HardwareComponentStatus: schema.HardwareComponentStatus{Status: &status},
	}}
	out := enrichPCIeWithRAIDTelemetry(devs)
	if out[0].BatteryHealthPct == nil || *out[0].BatteryHealthPct != 99 {
		t.Fatalf("battery health=%v", out[0].BatteryHealthPct)
	}
	if out[0].BatteryChargePct == nil || *out[0].BatteryChargePct != 81 {
		t.Fatalf("battery charge=%v", out[0].BatteryChargePct)
	}
	if out[0].BatteryVoltageV == nil || *out[0].BatteryVoltageV != 12.1 {
		t.Fatalf("battery voltage=%v", out[0].BatteryVoltageV)
	}
}
