package inspur

import (
	"strings"
	"testing"

	"git.mchus.pro/mchus/logpile/internal/models"
	"git.mchus.pro/mchus/logpile/internal/parser"
)

func TestParseAssetJSON_HddSlotFallbackAndPresence(t *testing.T) {
	content := []byte(`{
  "HddInfo": [
    {
      "PresentBitmap": [1],
      "SerialNumber": "",
      "Manufacturer": "",
      "ModelName": "",
      "FirmwareVersion": "",
      "Capacity": 0,
      "Location": 2,
      "DiskInterfaceType": 5,
      "MediaType": 1,
      "LocationString": ""
    }
  ]
}`)

	hw, err := ParseAssetJSON(content, nil, nil)
	if err != nil {
		t.Fatalf("ParseAssetJSON failed: %v", err)
	}
	if len(hw.Storage) != 1 {
		t.Fatalf("expected 1 storage entry, got %d", len(hw.Storage))
	}
	if hw.Storage[0].Slot != "OB03" {
		t.Fatalf("expected OB03 slot fallback, got %q", hw.Storage[0].Slot)
	}
	if !hw.Storage[0].Present {
		t.Fatalf("expected fallback storage entry marked present")
	}
	if hw.Storage[0].Type != "NVMe" {
		t.Fatalf("expected NVMe type, got %q", hw.Storage[0].Type)
	}
}

func TestParseDiskBackplaneInfo_PopulatesOnlyMissingPresentDrives(t *testing.T) {
	text := `RESTful diskbackplane info:
[
  { "port_count": 8, "driver_count": 4, "front": 1, "backplane_index": 0, "present": 1, "cpld_version": "3.1", "temperature": 18 },
  { "port_count": 8, "driver_count": 3, "front": 1, "backplane_index": 1, "present": 1, "cpld_version": "3.1", "temperature": 17 }
]
BMC`

	hw := &models.HardwareConfig{
		Storage: []models.Storage{
			{Slot: "OB01", Type: "NVMe", Present: true},
			{Slot: "OB02", Type: "NVMe", Present: true},
			{Slot: "OB03", Type: "NVMe", Present: true},
			{Slot: "OB04", Type: "NVMe", Present: true},
		},
	}

	parseDiskBackplaneInfo(text, hw)

	if len(hw.Storage) != 7 {
		t.Fatalf("expected total storage count 7 after backplane merge, got %d", len(hw.Storage))
	}
	bpCount := 0
	for _, dev := range hw.Storage {
		if strings.HasPrefix(dev.Slot, "BP0:") || strings.HasPrefix(dev.Slot, "BP1:") {
			bpCount++
		}
	}
	if bpCount != 3 {
		t.Fatalf("expected 3 synthetic backplane rows, got %d", bpCount)
	}
}

func TestEnrichStorageFromSerialFallbackFiles_AssignsSerials(t *testing.T) {
	files := []parser.ExtractedFile{
		{
			Path: "onekeylog/configuration/conf/BpHDDSerialNumber.info",
			Content: []byte{
				0xA0, 0xA1, 0xA2, 0xA3,
				'S', '6', 'K', 'N', 'N', 'G', '0', 'W', '4', '2', '8', '5', '5', '2',
				0x00,
				'P', 'H', 'Y', 'I', '5', '2', '7', '1', '0', '0', '4', 'B', '1', 'P', '9', 'D', 'G', 'N',
			},
		},
	}

	hw := &models.HardwareConfig{
		Storage: []models.Storage{
			{Slot: "BP0:0", Type: "HDD", Present: true},
			{Slot: "BP0:1", Type: "HDD", Present: true},
			{Slot: "OB01", Type: "NVMe", Present: true},
		},
	}

	enrichStorageFromSerialFallbackFiles(files, hw)

	if hw.Storage[0].SerialNumber == "" || hw.Storage[1].SerialNumber == "" {
		t.Fatalf("expected serials assigned to present storage entries, got %#v", hw.Storage)
	}
}
