package h3c

import (
	"strings"
	"testing"

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

func TestDetectH3C_GenerationRouting(t *testing.T) {
	g5 := &G5Parser{}
	g6 := &G6Parser{}

	g5Files := []parser.ExtractedFile{
		{Path: "bmc/pack.info", Content: []byte("STARTTIME:0")},
		{Path: "static/FRUInfo.ini", Content: []byte("[Baseboard]\nBoard Manufacturer=H3C\n")},
		{Path: "static/hardware_info.ini", Content: []byte("[Processors: Processor 1]\nModel: Intel Xeon\n")},
		{Path: "static/hardware.info", Content: []byte("[Disk_0_Front_NA]\nSerialNumber=DISK-0\n")},
		{Path: "static/firmware_version.ini", Content: []byte("[System board]\nBIOS Version: 5.59\n")},
		{Path: "user/test1.csv", Content: []byte("Record Time Stamp,DescInfo\n2025-01-01 00:00:00,foo\n")},
	}
	if gotG5, gotG6 := g5.Detect(g5Files), g6.Detect(g5Files); gotG5 <= gotG6 {
		t.Fatalf("expected G5 confidence > G6 for G5 sample, got g5=%d g6=%d", gotG5, gotG6)
	}

	g6Files := []parser.ExtractedFile{
		{Path: "bmc/pack.info", Content: []byte("STARTTIME:0")},
		{Path: "static/FRUInfo.ini", Content: []byte("[Baseboard]\nBoard Manufacturer=H3C\n")},
		{Path: "static/board_info.ini", Content: []byte("[System board]\nBoardMfr=H3C\n")},
		{Path: "static/firmware_version.json", Content: []byte(`{"BIOS":{"Firmware Name":"BIOS","Firmware Version":"6.10"}}`)},
		{Path: "static/CPUDetailInfo.xml", Content: []byte("<Root><CPU1><Model>X</Model></CPU1></Root>")},
		{Path: "static/MemoryDetailInfo.xml", Content: []byte("<Root><DIMM1><Name>A0</Name></DIMM1></Root>")},
		{Path: "user/Sel.json", Content: []byte(`{"Id":1}`)},
	}
	if gotG5, gotG6 := g5.Detect(g6Files), g6.Detect(g6Files); gotG6 <= gotG5 {
		t.Fatalf("expected G6 confidence > G5 for G6 sample, got g5=%d g6=%d", gotG5, gotG6)
	}
}

func TestParseH3CG6_RaidAndNVMeEnrichment(t *testing.T) {
	p := &G6Parser{}
	files := []parser.ExtractedFile{
		{
			Path: "static/storage_disk.ini",
			Content: []byte(`[Disk_000]
DiskSlotDesc=Front0
Present=YES
SerialNumber=SER-0
`),
		},
		{
			Path: "static/raid.json",
			Content: []byte(`{
  "RaidConfig": {
    "CtrlInfo": [
      {
        "CtrlSlot": 1,
        "CtrlName": "RAID-LSI-9560",
        "LDInfo": [
          {
            "LDID": "0",
            "LDName": "VD0",
            "RAIDLevel": "1",
            "CapacityBytes": 1000000000,
            "Status": "Optimal"
          }
        ]
      }
    ]
  }
}`),
		},
		{
			Path: "static/Storage_RAID-LSI-9560-LP-8i-4GB[1].txt",
			Content: []byte(`Controller Information
------------------------------------------------------------------------
AssetTag                                : RAID-LSI-9560

Logical Device Information
------------------------------------------------------------------------
LDID                                    : 0
Name                                    : VD0
RAID Level                              : 1
CapacityBytes                           : 1000000000
Status                                  : Optimal

Physical Device Information
------------------------------------------------------------------------
ConnectionID                            : 0
Position                                : Front0
StatusIndicator                         : OK
Protocol                                : SATA
MediaType                               : SSD
Manufacturer                            : Samsung
Model                                   : PM893
Revision                                : GDC1
SerialNumber                            : SER-0
CapacityBytes                           : 480000000000

ConnectionID                            : 1
Position                                : Front1
StatusIndicator                         : OK
Protocol                                : SATA
MediaType                               : SSD
Manufacturer                            : Samsung
Model                                   : PM893
Revision                                : GDC1
SerialNumber                            : SER-1
CapacityBytes                           : 480000000000
`),
		},
		{
			Path: "static/NVMe_info.txt",
			Content: []byte(`[NVMe_0]
Present=YES
DiskSlotDesc=Front2
Model=INTEL SSDPE2KX010T8
SerialNumber=NVME-1
Firmware=V100
CapacityBytes=1000204886016
Interface=NVMe
Status=OK
`),
		},
	}

	result, err := p.Parse(files)
	if err != nil {
		t.Fatalf("parse failed: %v", err)
	}
	if result.Hardware == nil {
		t.Fatalf("expected hardware section")
	}

	if len(result.Hardware.Volumes) != 1 {
		t.Fatalf("expected 1 volume, got %d", len(result.Hardware.Volumes))
	}
	vol := result.Hardware.Volumes[0]
	if vol.RAIDLevel != "RAID1" {
		t.Fatalf("expected RAID1 level, got %q", vol.RAIDLevel)
	}
	if vol.SizeGB != 1 {
		t.Fatalf("expected 1GB logical volume, got %d", vol.SizeGB)
	}

	if len(result.Hardware.Storage) != 3 {
		t.Fatalf("expected 3 unique storage devices, got %d", len(result.Hardware.Storage))
	}

	var front0 *models.Storage
	var nvme *models.Storage
	for i := range result.Hardware.Storage {
		s := &result.Hardware.Storage[i]
		if strings.EqualFold(s.SerialNumber, "SER-0") {
			front0 = s
		}
		if strings.EqualFold(s.SerialNumber, "NVME-1") {
			nvme = s
		}
	}
	if front0 == nil {
		t.Fatalf("expected merged Front0 disk by serial SER-0")
	}
	if front0.Model != "PM893" {
		t.Fatalf("expected Front0 model PM893, got %q", front0.Model)
	}
	if front0.SizeGB != 480 {
		t.Fatalf("expected Front0 size 480GB, got %d", front0.SizeGB)
	}
	if nvme == nil {
		t.Fatalf("expected NVMe disk by serial NVME-1")
	}
	if nvme.Type != "nvme" {
		t.Fatalf("expected nvme type, got %q", nvme.Type)
	}
}

func TestParseH3CG6(t *testing.T) {
	p := &G6Parser{}

	files := []parser.ExtractedFile{
		{
			Path: "static/FRUInfo.ini",
			Content: []byte(`[Baseboard]
Board Manufacturer=H3C
Board Product Name=RS36M2C6SB
Product Product Name=H3C UniServer R4700 G6
Product Serial Number=210235A4FYH257000010
Product Part Number=0235A4FY
`),
		},
		{
			Path: "static/firmware_version.json",
			Content: []byte(`{
  "BMCP": {"Firmware Name":"HDM","Firmware Version":"1.83","Location":"bmc card","Part Model":"-"},
  "BIOS": {"Firmware Name":"BIOS","Firmware Version":"6.10.53","Location":"system board","Part Model":"-"}
}`),
		},
		{
			Path: "static/CPUDetailInfo.xml",
			Content: []byte(`<Root>
  <CPU1>
    <Status>Presence</Status>
    <Model>INTEL(R) XEON(R) GOLD 6542Y</Model>
    <ProcessorSpeed>0xb54</ProcessorSpeed>
    <ProcessorMaxSpeed>0x1004</ProcessorMaxSpeed>
    <TotalCores>0x18</TotalCores>
    <TotalThreads>0x30</TotalThreads>
    <SerialNumber>68-5C-81-C1-0E-A3-4E-40</SerialNumber>
    <PPIN>68-5C-81-C1-0E-A3-4E-40</PPIN>
  </CPU1>
</Root>`),
		},
		{
			Path: "static/MemoryDetailInfo.xml",
			Content: []byte(`<Root>
  <DIMM1>
    <Status>Presence</Status>
    <Name>CPU1_CH1_D0 (A0)</Name>
    <PartNumber>M321R8GA0PB0-CWMXJ</PartNumber>
    <DIMMTech>RDIMM</DIMMTech>
    <SerialNumber>80CE032519135C82ED</SerialNumber>
    <DIMMRanks>0x2</DIMMRanks>
    <DIMMSize>0x10000</DIMMSize>
    <CurFreq>0x1130</CurFreq>
    <MaxFreq>0x15e0</MaxFreq>
    <DIMMSilk>A0</DIMMSilk>
  </DIMM1>
</Root>`),
		},
		{
			Path: "static/storage_disk.ini",
			Content: []byte(`[Disk_000]
SerialNumber=S6KLNN0Y516813
DiskSlotDesc=Front0
Present=YES
`),
		},
		{
			Path: "static/net_cfg.ini",
			Content: []byte(`[Network Configuration]
eth0      Link encap:Ethernet  HWaddr 30:C6:D7:94:54:F6
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

eth0.2    Link encap:Ethernet  HWaddr 30:C6:D7:94:54:F6
          inet6 addr: fe80::32c6:d7ff:fe94:54f6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1496  Metric:1

eth1      Link encap:Ethernet  HWaddr 30:C6:D7:94:54:F5
          inet addr:10.201.129.0  Bcast:10.201.143.255  Mask:255.255.240.0
          inet6 addr: fe80::32c6:d7ff:fe94:54f5/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
`),
		},
		{
			Path: "static/psu_cfg.ini",
			Content: []byte(`[Psu0]
SN=210231AGUNH257001569
Max_Power(W)=1600
Manufacturer=Great Wall
Power Status=Input Normal, Output Normal
Present_Status=Present
Power_ID=1
Model=GW-CRPS1600D2
Version=03.02.00

[Psu1]
Manufacturer=Great Wall
Power_ID=2
Version=03.02.00
Power Status=Input Normal, Output Normal
SN=210231AGUNH257001570
Model=GW-CRPS1600D2
Present_Status=Present
Max_Power(W)=1600
`),
		},
		{
			Path: "static/hardware_info.ini",
			Content: []byte(`[Ethernet adapters: Port 1]
Device Type                   : NIC
Network Port                  : Port 1
Location                      : PCIE-[1]
MAC Address                   : E4:3D:1A:6F:B0:30
Speed                         : 8.0GT/s
Product Name                  : NIC-BCM957414-F-B-25Gb-2P
[Ethernet adapters: Port 2]
Device Type                   : NIC
Network Port                  : Port 2
Location                      : PCIE-[1]
MAC Address                   : E4:3D:1A:6F:B0:31
Speed                         : 8.0GT/s
Product Name                  : NIC-BCM957414-F-B-25Gb-2P

[PCIe Card: PCIe 1]
Location                      : 1
Product Name                  : NIC-BCM957414-F-B-25Gb-2P
Status                        : Normal
Vendor ID                     : 0x14E4
Device ID                     : 0x16D7
Serial Number                 : NICSN-G6-001
Part Number                   : NICPN-G6-001
Firmware Version              : 22.35.1010
`),
		},
		{
			Path: "static/sensor_info.ini",
			Content: []byte(`Sensor Name      | Reading    | Unit       | Status| Crit low
Inlet_Temp       | 20.000     | degrees C  | ok    | na
CPU1_Status      | 0x0        | discrete   | 0x8080| na
`),
		},
		{
			Path: "user/Sel.json",
			Content: []byte(`
{
  "Created": "2025-07-14 03:34:18 UTC+08:00",
  "Severity": "Info",
  "EntryCode": "Asserted",
  "EntryType": "Event",
  "Id": 1,
  "Level": "Info",
  "Message": "Processor Presence detected",
  "SensorName": "CPU1_Status",
  "SensorType": "Processor"
},
{
  "Created": "2025-07-14 20:56:45 UTC+08:00",
  "Severity": "Critical",
  "EntryCode": "Asserted",
  "EntryType": "Event",
  "Id": 2,
  "Level": "Critical",
  "Message": "Power Supply AC lost",
  "SensorName": "PSU1_Status",
  "SensorType": "Power Supply"
}
`),
		},
	}

	result, err := p.Parse(files)
	if err != nil {
		t.Fatalf("parse failed: %v", err)
	}

	if result.Hardware == nil {
		t.Fatalf("expected hardware section")
	}
	if result.Hardware.BoardInfo.Manufacturer != "H3C" {
		t.Fatalf("unexpected board manufacturer: %q", result.Hardware.BoardInfo.Manufacturer)
	}
	if result.Hardware.BoardInfo.ProductName != "H3C UniServer R4700 G6" {
		t.Fatalf("unexpected board product: %q", result.Hardware.BoardInfo.ProductName)
	}
	if result.Hardware.BoardInfo.SerialNumber != "210235A4FYH257000010" {
		t.Fatalf("unexpected board serial: %q", result.Hardware.BoardInfo.SerialNumber)
	}

	if len(result.Hardware.Firmware) < 2 {
		t.Fatalf("expected firmware entries, got %d", len(result.Hardware.Firmware))
	}
	if len(result.Hardware.CPUs) != 1 {
		t.Fatalf("expected 1 cpu, got %d", len(result.Hardware.CPUs))
	}
	if result.Hardware.CPUs[0].Cores != 24 {
		t.Fatalf("expected 24 cores, got %d", result.Hardware.CPUs[0].Cores)
	}

	if len(result.Hardware.Memory) != 1 {
		t.Fatalf("expected 1 dimm, got %d", len(result.Hardware.Memory))
	}
	if result.Hardware.Memory[0].SizeMB != 65536 {
		t.Fatalf("expected 65536MB, got %d", result.Hardware.Memory[0].SizeMB)
	}

	if len(result.Hardware.Storage) != 1 {
		t.Fatalf("expected 1 disk, got %d", len(result.Hardware.Storage))
	}
	if result.Hardware.Storage[0].SerialNumber != "S6KLNN0Y516813" {
		t.Fatalf("unexpected disk serial: %q", result.Hardware.Storage[0].SerialNumber)
	}
	if len(result.Hardware.PowerSupply) != 2 {
		t.Fatalf("expected 2 PSUs from psu_cfg.ini, got %d", len(result.Hardware.PowerSupply))
	}
	if result.Hardware.PowerSupply[0].WattageW == 0 {
		t.Fatalf("expected PSU wattage parsed, got 0")
	}

	if len(result.Hardware.NetworkAdapters) != 1 {
		t.Fatalf("expected 1 host network adapter from hardware_info.ini, got %d", len(result.Hardware.NetworkAdapters))
	}
	macs := make(map[string]struct{})
	var hostNIC models.NetworkAdapter
	var hostNICFound bool
	for _, nic := range result.Hardware.NetworkAdapters {
		if len(nic.MACAddresses) == 0 {
			t.Fatalf("expected MAC on network adapter %+v", nic)
		}
		for _, mac := range nic.MACAddresses {
			macs[strings.ToLower(mac)] = struct{}{}
		}
		if strings.EqualFold(nic.Slot, "PCIe 1") && strings.Contains(strings.ToLower(nic.Model), "bcm957414") {
			hostNIC = nic
			hostNICFound = true
		}
	}
	if !hostNICFound {
		t.Fatalf("expected host NIC from hardware_info.ini, got %+v", result.Hardware.NetworkAdapters)
	}
	if _, ok := macs["e4:3d:1a:6f:b0:30"]; !ok {
		t.Fatalf("expected host NIC MAC e4:3d:1a:6f:b0:30 in adapters, got %+v", result.Hardware.NetworkAdapters)
	}
	if _, ok := macs["e4:3d:1a:6f:b0:31"]; !ok {
		t.Fatalf("expected host NIC MAC e4:3d:1a:6f:b0:31 in adapters, got %+v", result.Hardware.NetworkAdapters)
	}
	if !strings.Contains(strings.ToLower(hostNIC.Vendor), "broadcom") {
		t.Fatalf("expected host NIC vendor enrichment from Vendor ID, got %q", hostNIC.Vendor)
	}
	if hostNIC.SerialNumber != "NICSN-G6-001" {
		t.Fatalf("expected host NIC serial from PCIe card section, got %q", hostNIC.SerialNumber)
	}
	if hostNIC.PartNumber != "NICPN-G6-001" {
		t.Fatalf("expected host NIC part number from PCIe card section, got %q", hostNIC.PartNumber)
	}
	if hostNIC.Firmware != "22.35.1010" {
		t.Fatalf("expected host NIC firmware from PCIe card section, got %q", hostNIC.Firmware)
	}

	if len(result.Sensors) != 2 {
		t.Fatalf("expected 2 sensors, got %d", len(result.Sensors))
	}
	if result.Sensors[0].Name != "Inlet_Temp" {
		t.Fatalf("unexpected first sensor: %q", result.Sensors[0].Name)
	}

	if len(result.Events) != 2 {
		t.Fatalf("expected 2 events, got %d", len(result.Events))
	}
	if result.Events[0].Timestamp.Year() != 2025 || result.Events[0].Timestamp.Month() != 7 {
		t.Fatalf("expected SEL timestamp from payload, got %s", result.Events[0].Timestamp)
	}
	if result.Events[1].Severity != models.SeverityCritical {
		t.Fatalf("expected critical severity for AC lost event, got %q", result.Events[1].Severity)
	}
}

func TestParseH3CG5_PCIeArgumentsEnrichesNonNVMeStorage(t *testing.T) {
	p := &G5Parser{}
	files := []parser.ExtractedFile{
		{
			Path: "static/storage_disk.ini",
			Content: []byte(`[Disk_000]
DiskSlotDesc=Front slot 3
Present=YES
SerialNumber=SAT-03
`),
		},
		{
			Path: "static/NVMe_info.txt",
			Content: []byte(`[NVMe_0]
Present=YES
DiskSlotDesc=Front slot 108
SerialNumber=NVME-108
`),
		},
		{
			Path: "static/PCIe_arguments_table.xml",
			Content: []byte(`<root>
  <PCIE100>
    <base_args>
      <type>SSD</type>
      <name>SSD-SATA-960G</name>
    </base_args>
    <type_get_args>
      <bios_args>
        <vendor_id>0x144D</vendor_id>
      </bios_args>
    </type_get_args>
  </PCIE100>
  <PCIE200>
    <base_args>
      <type>SSD</type>
      <name>SSD-3.84T-NVMe-SFF</name>
    </base_args>
    <type_get_args>
      <bios_args>
        <vendor_id>0x144D</vendor_id>
      </bios_args>
    </type_get_args>
  </PCIE200>
</root>`),
		},
	}

	result, err := p.Parse(files)
	if err != nil {
		t.Fatalf("parse failed: %v", err)
	}
	if result.Hardware == nil {
		t.Fatalf("expected hardware section")
	}

	if len(result.Hardware.Storage) != 2 {
		t.Fatalf("expected 2 storage devices, got %d", len(result.Hardware.Storage))
	}

	var sata *models.Storage
	var nvme *models.Storage
	for i := range result.Hardware.Storage {
		s := &result.Hardware.Storage[i]
		switch s.SerialNumber {
		case "SAT-03":
			sata = s
		case "NVME-108":
			nvme = s
		}
	}

	if sata == nil {
		t.Fatalf("expected SATA storage SAT-03")
	}
	if sata.Model != "SSD-SATA-960G" {
		t.Fatalf("expected SATA model enrichment from PCIe table, got %q", sata.Model)
	}
	if !strings.Contains(strings.ToLower(sata.Manufacturer), "samsung") {
		t.Fatalf("expected SATA vendor enrichment to Samsung, got %q", sata.Manufacturer)
	}

	if nvme == nil {
		t.Fatalf("expected NVMe storage NVME-108")
	}
	if nvme.Model != "SSD-3.84T-NVMe-SFF" {
		t.Fatalf("expected NVMe model enrichment from PCIe table, got %q", nvme.Model)
	}
	if !strings.Contains(strings.ToLower(nvme.Manufacturer), "samsung") {
		t.Fatalf("expected NVMe vendor enrichment to Samsung, got %q", nvme.Manufacturer)
	}
}

func TestParseH3CG5_VariantLayout(t *testing.T) {
	p := &G5Parser{}

	files := []parser.ExtractedFile{
		{
			Path: "static/FRUInfo.ini",
			Content: []byte(`[Baseboard]
Board Manufacturer=H3C
Product Product Name=H3C UniServer R4900 G5
Product Serial Number=02A6AX5231C003VM
`),
		},
		{
			Path: "static/firmware_version.ini",
			Content: []byte(`[System board]
BIOS Version                  : 5.59 V100R001B05D078
ME Version                    : 4.4.4.202
HDM Version                   : 3.34.01 HDM V100R001B05D078SP01
CPLD Version                  : V00C
`),
		},
		{
			Path: "static/board_cfg.ini",
			Content: []byte(`[Board Type]
Board Type                    : R4900 G5

[Board Version]
Board Version                 : VER.D

[Customer ID]
CustomerID                    : 255

[OEM ID]
OEM Flag                      : 1
`),
		},
		{
			Path: "static/hardware_info.ini",
			Content: []byte(`[Processors: Processor 1]
Model                         : Intel(R) Xeon(R) Gold 6342 CPU @ 2.80GHz
Status                        : Normal
Frequency                     : 2800 MHz
Cores                         : 24
Threads                       : 48
L1 Cache                      : 1920 KB
L2 Cache                      : 30720 KB
L3 Cache                      : 36864 KB
CPU PPIN                      : 49-A9-50-C0-15-9F-2D-DC

[Processors: Processor 2]
Model                         : Intel(R) Xeon(R) Gold 6342 CPU @ 2.80GHz
Status                        : Normal
Frequency                     : 2800 MHz
Cores                         : 24
Threads                       : 48
CPU PPIN                      : 49-AC-3D-BF-85-7F-17-58

[Memory Details: Dimm Index 0]
Location                      : Processor 1
Channel                       : 1
Socket ID                     : A0
Status                        : Normal
Size                          : 65536 MB
Maximum Frequency             : 3200 MHz
Type                          : DDR4
Ranks                         : 2R DIMM
Technology                    : RDIMM
Part Number                   : M393A8G40AB2-CWE
Manufacture                   : Samsung
Serial Number                 : S02K0D0243351D7079

[Memory Details: Dimm Index 16]
Location                      : Processor 2
Channel                       : 1
Socket ID                     : A0
Status                        : Normal
Size                          : 65536 MB
Maximum Frequency             : 3200 MHz
Type                          : DDR4
Ranks                         : 2R DIMM
Technology                    : RDIMM
Part Number                   : M393A8G40AB2-CWE
Manufacture                   : Samsung
Serial Number                 : S02K0D0243351D73F0

[Ethernet adapters: Port 1]
Device Type                   : NIC
Network Port                  : Port 1
Location                      : PCIE-[1]
MAC Address                   : E4:3D:1A:6F:B0:30
Speed                         : 8.0GT/s
Product Name                  : NIC-BCM957414-F-B-25Gb-2P
[Ethernet adapters: Port 2]
Device Type                   : NIC
Network Port                  : Port 2
Location                      : PCIE-[1]
MAC Address                   : E4:3D:1A:6F:B0:31
Speed                         : 8.0GT/s
Product Name                  : NIC-BCM957414-F-B-25Gb-2P

[Ethernet adapters: Port 1]
Device Type                   : NIC
Network Port                  : Port 1
Location                      : PCIE-[4]
MAC Address                   : E8:EB:D3:4F:2E:90
Speed                         : 8.0GT/s
Product Name                  : NIC-MCX512A-ACAT-2*25Gb-F
[Ethernet adapters: Port 2]
Device Type                   : NIC
Network Port                  : Port 2
Location                      : PCIE-[4]
MAC Address                   : E8:EB:D3:4F:2E:91
Speed                         : 8.0GT/s
Product Name                  : NIC-MCX512A-ACAT-2*25Gb-F

[PCIe Card: PCIe 1]
Location                      : 1
Product Name                  : NIC-BCM957414-F-B-25Gb-2P
Status                        : Normal
Vendor ID                     : 0x14E4
Device ID                     : 0x16D7
Serial Number                 : NICSN-G5-001
Part Number                   : NICPN-G5-001
Firmware Version              : 21.80.1

[PCIe Card: PCIe 4]
Location                      : 4
Product Name                  : NIC-MCX512A-ACAT-2*25Gb-F
Status                        : Normal
Vendor ID                     : 0x15B3
Device ID                     : 0x1017
Serial Number                 : NICSN-G5-004
Part Number                   : NICPN-G5-004
Firmware Version              : 28.33.15
`),
		},
		{
			Path: "static/hardware.info",
			Content: []byte(`[Disk_0_Front_NA]
Present=YES
SlotNum=0
FrontOrRear=Front
SerialNumber=22443C4EE184

[Nvme_Front slot 21]
Present=YES
NvmePhySlot=Front slot 21
SlotNum=121
SerialNumber=NVME-21

[Nvme_255_121]
Present=YES
SlotNum=121
SerialNumber=NVME-21
`),
		},
		{
			Path: "static/raid.json",
			Content: []byte(`{
  "RAIDCONFIG": {
    "Ctrl info": [
      {
        "CtrlDevice Slot": 3,
        "CtrlDevice Name": "AVAGO MegaRAID SAS 9460-8i",
        "LDInfo": [
          {
            "LD ID": 0,
            "LD_name": "SystemRAID",
            "RAID_level(RAID 0,RAID 1,RAID 5,RAID 6,RAID 00,RAID 10,RAID 50,RAID 60)": "RAID1",
            "Logical_capicity(per 512byte)": 936640512
          }
        ]
      },
      {
        "CtrlDevice Slot": 6,
        "CtrlDevice Name": "MegaRAID 9560-16i 8GB",
        "LDInfo": [
          {
            "LD ID": 0,
            "LD_name": "DataRAID",
            "RAID_level(RAID 0,RAID 1,RAID 5,RAID 6,RAID 00,RAID 10,RAID 50,RAID 60)": "RAID50",
            "Logical_capicity(per 512byte)": 90004783104
          }
        ]
      }
    ]
  }
}`),
		},
		{
			Path: "static/Raid_BP_Conf_Info.ini",
			Content: []byte(`[BP Information]
Description                  | BP TYPE                          | I2cPort        | BpConnectorNum        | FrontOrRear | Node Num   | DiskSlotRange       |
8SFF SAS/SATA                | BP_G5_8SFF                       | AUX_1          | ~                     | ~           | ~          | ~                   |
8SFF SAS/SATA                | BP_G5_8SFF                       | AUX_2          | ~                     | ~           | ~          | ~                   |
8SFF SAS/SATA                | BP_G5_8SFF                       | AUX_3          | ~                     | ~           | ~          | ~                   |

[RAID Information]
PCIE SLOT  | RAID SAS_NUM |
3          | 2            |
6          | 4            |
`),
		},
		{
			Path: "static/PCIe_arguments_table.xml",
			Content: []byte(`<root>
  <PCIE100>
    <base_args>
      <type>SSD</type>
      <name>SSD-1.92T/3.84T-NVMe-EV-SFF-sa</name>
    </base_args>
    <type_get_args>
      <bios_args>
        <vendor_id>0x144D</vendor_id>
      </bios_args>
    </type_get_args>
  </PCIE100>
</root>`),
		},
		{
			Path: "static/psu_cfg.ini",
			Content: []byte(`[Active / Standby configuration]
Power ID                      : 1
Present Status                : Present
Cold Status                   : Active Power
Model                         : DPS-1300AB-6 R
SN                            : 210231ACT9H232000080
Max Power(W)                  : 1300

Power ID                      : 2
Present Status                : Present
Cold Status                   : Active Power
Model                         : DPS-1300AB-6 R
SN                            : 210231ACT9H232000079
Max Power(W)                  : 1300
`),
		},
		{
			Path: "static/net_cfg.ini",
			Content: []byte(`[Network Configuration]
eth0      Link encap:Ethernet  HWaddr 30:C6:D7:94:54:F6
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

eth0.2    Link encap:Ethernet  HWaddr 30:C6:D7:94:54:F6
          inet6 addr: fe80::32c6:d7ff:fe94:54f6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1496  Metric:1

eth1      Link encap:Ethernet  HWaddr 30:C6:D7:94:54:F5
          inet addr:10.201.129.0  Bcast:10.201.143.255  Mask:255.255.240.0
          inet6 addr: fe80::32c6:d7ff:fe94:54f5/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
`),
		},
		{
			Path: "static/smartdata/Front0/first_date_analysis.txt",
			Content: []byte(`The Current System Time Is 2023_09_22_14_19_39
Model Info: ATA Micron_5300_MTFD
Serial Number: 22443C4EE184
`),
		},
		{
			Path: "user/test1.csv",
			Content: []byte(`Record Time Stamp,Severity Level,Severity Level ID,SensorTypeStr,SensorName,Event Dir,Event Occurred Time,DescInfo,Explanation,Suggestion
2025-04-01 08:50:13,Minor,0x1,NA,NA,NA,2025-04-01 08:50:13,"SSH login failed from IP: 10.200.10.121 user: admin"," "," "
Pre-Init,Info,0x0,Management Subsystem Health,Health,Assertion event,Pre-Init,"Management controller off-line"," "," "
2025-04-01 08:51:10,Major,0x2,Power Supply,PSU1_Status,Assertion event,2025-04-01 08:51:10,"Power Supply AC lost"," "," "
`),
		},
	}

	result, err := p.Parse(files)
	if err != nil {
		t.Fatalf("parse failed: %v", err)
	}
	if result.Hardware == nil {
		t.Fatalf("expected hardware section")
	}

	if len(result.Hardware.CPUs) != 2 {
		t.Fatalf("expected 2 CPUs from hardware_info.ini, got %d", len(result.Hardware.CPUs))
	}
	if result.Hardware.CPUs[0].FrequencyMHz != 2800 {
		t.Fatalf("expected CPU frequency 2800MHz, got %d", result.Hardware.CPUs[0].FrequencyMHz)
	}

	if len(result.Hardware.Memory) != 2 {
		t.Fatalf("expected 2 DIMMs from hardware_info.ini, got %d", len(result.Hardware.Memory))
	}
	if result.Hardware.Memory[0].SizeMB != 65536 {
		t.Fatalf("expected DIMM size 65536MB, got %d", result.Hardware.Memory[0].SizeMB)
	}

	if len(result.Hardware.Firmware) < 4 {
		t.Fatalf("expected firmware entries from firmware_version.ini, got %d", len(result.Hardware.Firmware))
	}
	if result.Hardware.BoardInfo.Version == "" {
		t.Fatalf("expected board version from board_cfg.ini")
	}
	if !strings.Contains(result.Hardware.BoardInfo.Description, "CustomerID: 255") {
		t.Fatalf("expected board description enrichment from board_cfg.ini, got %q", result.Hardware.BoardInfo.Description)
	}

	if len(result.Hardware.Storage) != 2 {
		t.Fatalf("expected 2 unique storage devices from hardware.info, got %d", len(result.Hardware.Storage))
	}
	var nvmeFound bool
	var diskModelEnriched bool
	for _, s := range result.Hardware.Storage {
		if s.SerialNumber == "NVME-21" {
			nvmeFound = true
			if s.Type != "nvme" {
				t.Fatalf("expected NVME-21 type nvme, got %q", s.Type)
			}
			if !strings.Contains(strings.ToLower(s.Manufacturer), "samsung") {
				t.Fatalf("expected NVME vendor enrichment to Samsung, got %q", s.Manufacturer)
			}
			if s.Model != "SSD-1.92T/3.84T-NVMe-EV-SFF-sa" {
				t.Fatalf("expected NVME model enrichment from PCIe table, got %q", s.Model)
			}
		}
		if s.SerialNumber == "22443C4EE184" && strings.Contains(s.Model, "Micron") {
			diskModelEnriched = true
		}
	}
	if !nvmeFound {
		t.Fatalf("expected deduped NVME storage by serial NVME-21")
	}
	if !diskModelEnriched {
		t.Fatalf("expected disk model enrichment from smartdata by serial")
	}

	if len(result.Hardware.PowerSupply) != 2 {
		t.Fatalf("expected 2 PSUs from psu_cfg.ini, got %d", len(result.Hardware.PowerSupply))
	}
	if result.Hardware.PowerSupply[0].WattageW == 0 {
		t.Fatalf("expected PSU wattage parsed, got 0")
	}
	if len(result.Hardware.NetworkAdapters) != 2 {
		t.Fatalf("expected 2 host network adapters from hardware_info.ini, got %d", len(result.Hardware.NetworkAdapters))
	}
	if len(result.Hardware.NetworkCards) != 2 {
		t.Fatalf("expected 2 network cards synthesized from adapters, got %d", len(result.Hardware.NetworkCards))
	}
	var g5NIC models.NetworkAdapter
	var g5NICFound bool
	for _, nic := range result.Hardware.NetworkAdapters {
		if strings.EqualFold(nic.Slot, "PCIe 1") && strings.Contains(strings.ToLower(nic.Model), "bcm957414") {
			g5NIC = nic
			g5NICFound = true
			break
		}
	}
	if !g5NICFound {
		t.Fatalf("expected host NIC PCIe 1 from hardware_info.ini, got %+v", result.Hardware.NetworkAdapters)
	}
	if !strings.Contains(strings.ToLower(g5NIC.Vendor), "broadcom") {
		t.Fatalf("expected G5 NIC vendor from Vendor ID, got %q", g5NIC.Vendor)
	}
	if g5NIC.SerialNumber != "NICSN-G5-001" {
		t.Fatalf("expected G5 NIC serial from PCIe card section, got %q", g5NIC.SerialNumber)
	}
	if g5NIC.PartNumber != "NICPN-G5-001" {
		t.Fatalf("expected G5 NIC part number from PCIe card section, got %q", g5NIC.PartNumber)
	}
	if g5NIC.Firmware != "21.80.1" {
		t.Fatalf("expected G5 NIC firmware from PCIe card section, got %q", g5NIC.Firmware)
	}

	if len(result.Hardware.Devices) != 5 {
		t.Fatalf("expected 5 topology devices from Raid_BP_Conf_Info.ini (3 BP + 2 RAID), got %d", len(result.Hardware.Devices))
	}
	var bpFound bool
	var raidFound bool
	for _, d := range result.Hardware.Devices {
		if strings.Contains(d.ID, "h3c-bp-") && strings.Contains(d.Model, "BP_G5_8SFF") {
			bpFound = true
		}
		desc, _ := d.Details["description"].(string)
		if strings.Contains(d.ID, "h3c-raid-slot-3") && strings.Contains(desc, "SAS ports: 2") {
			raidFound = true
		}
	}
	if !bpFound || !raidFound {
		t.Fatalf("expected parsed backplane and RAID topology devices, got %+v", result.Hardware.Devices)
	}

	if len(result.Hardware.Volumes) != 2 {
		t.Fatalf("expected 2 RAID volumes (same LD ID on different controllers), got %d", len(result.Hardware.Volumes))
	}
	var raid1Found bool
	var raid50Found bool
	for _, v := range result.Hardware.Volumes {
		if strings.Contains(v.Controller, "slot 3") {
			raid1Found = v.RAIDLevel == "RAID1" && v.CapacityBytes > 0
		}
		if strings.Contains(v.Controller, "slot 6") {
			raid50Found = v.RAIDLevel == "RAID50" && v.CapacityBytes > 0
		}
	}
	if !raid1Found || !raid50Found {
		t.Fatalf("expected RAID1 and RAID50 volumes with parsed capacities, got %+v", result.Hardware.Volumes)
	}

	if len(result.Events) != 2 {
		t.Fatalf("expected 2 CSV events (Pre-Init skipped), got %d", len(result.Events))
	}
	if result.Events[0].Severity != models.SeverityWarning {
		t.Fatalf("expected Minor CSV severity mapped to warning, got %q", result.Events[0].Severity)
	}
	if result.Events[1].Severity != models.SeverityCritical {
		t.Fatalf("expected Major CSV severity mapped to critical, got %q", result.Events[1].Severity)
	}
}
