package nvidia

import (
	"strings"
	"testing"

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

func TestApplyGPUStatuses_FromSummaryCSV_FailAndPass(t *testing.T) {
	csvData := strings.Join([]string{
		"ErrorCode,Test,VirtualID,SubTest,Type,ComponentID,Notes,Level,,,IgnoreError",
		"0,gpumem,gpumem,,GPU,SXM1_SN_111,OK,1,,,False",
		"363,gpumem,gpumem,,GPU,SXM5_SN_1653925025497,Row remapping failed,1,,,False",
		"0,gpu_fieldiag,gpu_fieldiag,,GPU,SXM1_SN_111,OK,1,,,False",
		"0,gpu_fieldiag,gpu_fieldiag,,GPU,SXM2_SN_222,OK,1,,,False",
	}, "\n")

	result := &models.AnalysisResult{
		Hardware: &models.HardwareConfig{
			GPUs: []models.GPU{
				{Slot: "GPUSXM1", SerialNumber: "111"},
				{Slot: "GPUSXM2", SerialNumber: "222"},
				{Slot: "GPUSXM5", SerialNumber: "1653925025497"},
			},
		},
	}

	statuses := CollectGPUStatusesFromSummaryCSV([]byte(csvData))
	ApplyGPUStatuses(result, statuses)

	bySerial := map[string]string{}
	for _, gpu := range result.Hardware.GPUs {
		bySerial[gpu.SerialNumber] = gpu.Status
	}

	if bySerial["1653925025497"] != "FAIL" {
		t.Fatalf("expected serial 1653925025497 status FAIL, got %q", bySerial["1653925025497"])
	}
	if bySerial["111"] != "PASS" {
		t.Fatalf("expected serial 111 status PASS, got %q", bySerial["111"])
	}
	if bySerial["222"] != "PASS" {
		t.Fatalf("expected serial 222 status PASS, got %q", bySerial["222"])
	}
}

func TestApplyGPUFailureDetails_FromSummaryJSON_BySerial(t *testing.T) {
	jsonData := []byte(`[
		{
			"Error Code": "005-000-1-000000000363",
			"Test": "gpumem",
			"Component ID": "SXM5_SN_1653925025497",
			"Notes": "Row remapping failed",
			"Virtual ID": "gpumem",
			"Ignore Error": "False"
		}
	]`)

	result := &models.AnalysisResult{
		Hardware: &models.HardwareConfig{
			GPUs: []models.GPU{
				{Slot: "GPUSXM5", SerialNumber: "1653925025497"},
				{Slot: "GPUSXM2", SerialNumber: "1653925024190"},
			},
		},
	}

	details := CollectGPUFailureDetailsFromSummaryJSON(jsonData)
	ApplyGPUFailureDetails(result, details)

	if got := result.Hardware.GPUs[0].ErrorDescription; got != "Row remapping failed" {
		t.Fatalf("expected serial 1653925025497 error Row remapping failed, got %q", got)
	}
	if got := result.Hardware.GPUs[1].ErrorDescription; got != "" {
		t.Fatalf("expected no error description for healthy GPU, got %q", got)
	}
}

func TestApplyNVSwitchStatuses_FromSummaryJSON(t *testing.T) {
	jsonData := []byte(`[
		{
			"Error Code": "0",
			"Test": "inventory",
			"Component ID": "NVSWITCH_NVSWITCH0_VendorID",
			"Notes": "OK",
			"Virtual ID": "inventory",
			"Ignore Error": "False"
		},
		{
			"Error Code": "1",
			"Test": "inventory",
			"Component ID": "NVSWITCH_NVSWITCH1_LinkState",
			"Notes": "Link down",
			"Virtual ID": "inventory",
			"Ignore Error": "False"
		}
	]`)

	result := &models.AnalysisResult{
		Hardware: &models.HardwareConfig{
			PCIeDevices: []models.PCIeDevice{
				{Slot: "NVSWITCH0", Status: "Unknown"},
				{Slot: "NVSWITCH1", Status: "Unknown"},
				{Slot: "NVSWITCH2", Status: "Unknown"},
			},
		},
	}

	statuses := CollectNVSwitchStatusesFromSummaryJSON(jsonData)
	ApplyNVSwitchStatuses(result, statuses)

	if got := result.Hardware.PCIeDevices[0].Status; got != "PASS" {
		t.Fatalf("expected NVSWITCH0 status PASS, got %q", got)
	}
	if got := result.Hardware.PCIeDevices[1].Status; got != "FAIL" {
		t.Fatalf("expected NVSWITCH1 status FAIL, got %q", got)
	}
	if got := result.Hardware.PCIeDevices[2].Status; got != "Unknown" {
		t.Fatalf("expected NVSWITCH2 status unchanged Unknown, got %q", got)
	}
}
