package exporter

import (
	"encoding/json"
	"strings"
	"testing"
	"time"

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

// TestFullReanimatorExport tests complete export with realistic data
func TestFullReanimatorExport(t *testing.T) {
	// Create a realistic AnalysisResult similar to import-example-full.json
	result := &models.AnalysisResult{
		Filename:    "redfish://10.10.10.103",
		SourceType:  "api",
		Protocol:    "redfish",
		TargetHost:  "10.10.10.103",
		CollectedAt: time.Date(2026, 2, 10, 15, 30, 0, 0, time.UTC),
		Hardware: &models.HardwareConfig{
			BoardInfo: models.BoardInfo{
				Manufacturer: "Supermicro",
				ProductName:  "X12DPG-QT6",
				SerialNumber: "21D634101",
				PartNumber:   "X12DPG-QT6-REV1.01",
				UUID:         "d7ef2fe5-2fd0-11f0-910a-346f11040868",
			},
			Firmware: []models.FirmwareInfo{
				{DeviceName: "BIOS", Version: "06.08.05"},
				{DeviceName: "BMC", Version: "5.17.00"},
				{DeviceName: "CPLD", Version: "01.02.03"},
			},
			CPUs: []models.CPU{
				{
					Socket:       0,
					Model:        "INTEL(R) XEON(R) GOLD 6530",
					Cores:        32,
					Threads:      64,
					FrequencyMHz: 2100,
					MaxFreqMHz:   4000,
				},
				{
					Socket:       1,
					Model:        "INTEL(R) XEON(R) GOLD 6530",
					Cores:        32,
					Threads:      64,
					FrequencyMHz: 2100,
					MaxFreqMHz:   4000,
				},
			},
			Memory: []models.MemoryDIMM{
				{
					Slot:            "CPU0_C0D0",
					Location:        "CPU0_C0D0",
					Present:         true,
					SizeMB:          32768,
					Type:            "DDR5",
					MaxSpeedMHz:     4800,
					CurrentSpeedMHz: 4800,
					Manufacturer:    "Hynix",
					SerialNumber:    "80AD032419E17CEEC1",
					PartNumber:      "HMCG88AGBRA191N",
					Status:          "OK",
				},
				{
					Slot:            "CPU0_C1D0",
					Location:        "CPU0_C1D0",
					Present:         false,
					SizeMB:          0,
					Type:            "",
					MaxSpeedMHz:     0,
					CurrentSpeedMHz: 0,
					Status:          "Empty",
				},
			},
			Storage: []models.Storage{
				{
					Slot:         "OB01",
					Type:         "NVMe",
					Model:        "INTEL SSDPF2KX076T1",
					SizeGB:       7680,
					SerialNumber: "BTAX41900GF87P6DGN",
					Manufacturer: "Intel",
					Firmware:     "9CV10510",
					Interface:    "NVMe",
					Present:      true,
				},
				{
					Slot:         "FP00HDD00",
					Type:         "HDD",
					Model:        "ST12000NM0008",
					SizeGB:       12000,
					SerialNumber: "ZJV01234ABC",
					Manufacturer: "Seagate",
					Firmware:     "SN03",
					Interface:    "SATA",
					Present:      true,
				},
			},
			PCIeDevices: []models.PCIeDevice{
				{
					Slot:         "PCIeCard1",
					VendorID:     32902,
					DeviceID:     2912,
					BDF:          "0000:18:00.0",
					DeviceClass:  "MassStorageController",
					Manufacturer: "Intel",
					PartNumber:   "RAID Controller RSP3DD080F",
					LinkWidth:    8,
					LinkSpeed:    "Gen3",
					MaxLinkWidth: 8,
					MaxLinkSpeed: "Gen3",
					SerialNumber: "RAID-001-12345",
				},
				{
					Slot:         "PCIeCard2",
					VendorID:     5555,
					DeviceID:     4401,
					BDF:          "0000:3b:00.0",
					DeviceClass:  "NetworkController",
					Manufacturer: "Mellanox",
					PartNumber:   "ConnectX-5",
					LinkWidth:    16,
					LinkSpeed:    "Gen3",
					MaxLinkWidth: 16,
					MaxLinkSpeed: "Gen3",
					SerialNumber: "MT2892012345",
				},
			},
			PowerSupply: []models.PSU{
				{
					Slot:         "0",
					Present:      true,
					Model:        "GW-CRPS3000LW",
					Vendor:       "Great Wall",
					WattageW:     3000,
					SerialNumber: "2P06C102610",
					PartNumber:   "V0310C9000000000",
					Firmware:     "00.03.05",
					Status:       "OK",
					InputType:    "ACWideRange",
					InputPowerW:  137,
					OutputPowerW: 104,
					InputVoltage: 215.25,
				},
			},
		},
	}

	// Convert to Reanimator format
	reanimator, err := ConvertToReanimator(result)
	if err != nil {
		t.Fatalf("ConvertToReanimator failed: %v", err)
	}

	// Verify top-level fields
	if reanimator.Filename != "redfish://10.10.10.103" {
		t.Errorf("Filename mismatch: got %q", reanimator.Filename)
	}

	if reanimator.SourceType != "api" {
		t.Errorf("SourceType mismatch: got %q", reanimator.SourceType)
	}

	if reanimator.Protocol != "redfish" {
		t.Errorf("Protocol mismatch: got %q", reanimator.Protocol)
	}

	if reanimator.TargetHost != "10.10.10.103" {
		t.Errorf("TargetHost mismatch: got %q", reanimator.TargetHost)
	}

	if reanimator.CollectedAt != "2026-02-10T15:30:00Z" {
		t.Errorf("CollectedAt mismatch: got %q", reanimator.CollectedAt)
	}

	// Verify hardware sections
	hw := reanimator.Hardware

	// Board
	if hw.Board.SerialNumber != "21D634101" {
		t.Errorf("Board serial mismatch: got %q", hw.Board.SerialNumber)
	}

	// Firmware
	if len(hw.Firmware) != 3 {
		t.Errorf("Expected 3 firmware entries, got %d", len(hw.Firmware))
	}

	// CPUs
	if len(hw.CPUs) != 2 {
		t.Fatalf("Expected 2 CPUs, got %d", len(hw.CPUs))
	}

	if hw.CPUs[0].Manufacturer != "Intel" {
		t.Errorf("CPU manufacturer not inferred: got %q", hw.CPUs[0].Manufacturer)
	}

	if hw.CPUs[0].Status != "Unknown" {
		t.Errorf("CPU status mismatch: got %q", hw.CPUs[0].Status)
	}

	// Memory (empty slots are excluded)
	if len(hw.Memory) != 1 {
		t.Errorf("Expected 1 memory entry (installed only), got %d", len(hw.Memory))
	}

	// Storage
	if len(hw.Storage) != 2 {
		t.Errorf("Expected 2 storage devices, got %d", len(hw.Storage))
	}

	if hw.Storage[0].Status != "Unknown" {
		t.Errorf("Storage status mismatch: got %q", hw.Storage[0].Status)
	}

	// PCIe devices
	if len(hw.PCIeDevices) != 2 {
		t.Errorf("Expected 2 PCIe devices, got %d", len(hw.PCIeDevices))
	}

	if hw.PCIeDevices[0].Model == "" {
		t.Error("PCIe model should be populated from PartNumber")
	}

	// Power supplies
	if len(hw.PowerSupplies) != 1 {
		t.Errorf("Expected 1 PSU, got %d", len(hw.PowerSupplies))
	}

	// Verify JSON marshaling works
	jsonData, err := json.MarshalIndent(reanimator, "", "  ")
	if err != nil {
		t.Fatalf("Failed to marshal to JSON: %v", err)
	}

	// Check that JSON contains expected fields
	jsonStr := string(jsonData)
	expectedFields := []string{
		`"filename"`,
		`"source_type"`,
		`"protocol"`,
		`"target_host"`,
		`"collected_at"`,
		`"hardware"`,
		`"board"`,
		`"cpus"`,
		`"memory"`,
		`"storage"`,
		`"pcie_devices"`,
		`"power_supplies"`,
		`"firmware"`,
	}

	for _, field := range expectedFields {
		if !strings.Contains(jsonStr, field) {
			t.Errorf("JSON missing expected field: %s", field)
		}
	}

	// Optional: print JSON for manual inspection (commented out for normal test runs)
	// t.Logf("Generated Reanimator JSON:\n%s", string(jsonData))
}

// TestReanimatorExportWithoutTargetHost tests that target_host is inferred from filename
func TestReanimatorExportWithoutTargetHost(t *testing.T) {
	result := &models.AnalysisResult{
		Filename:    "redfish://192.168.1.100",
		SourceType:  "api",
		Protocol:    "redfish",
		TargetHost:  "", // Empty - should be inferred
		CollectedAt: time.Now(),
		Hardware: &models.HardwareConfig{
			BoardInfo: models.BoardInfo{
				SerialNumber: "TEST123",
			},
		},
	}

	reanimator, err := ConvertToReanimator(result)
	if err != nil {
		t.Fatalf("ConvertToReanimator failed: %v", err)
	}

	if reanimator.TargetHost != "192.168.1.100" {
		t.Errorf("Expected target_host to be inferred from filename, got %q", reanimator.TargetHost)
	}
}
