package parser

import (
	"archive/tar"
	"bytes"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

func TestExtractArchiveFromReaderTXT(t *testing.T) {
	content := "loader_brand=\"XigmaNAS\"\nSystem uptime:\n"
	files, err := ExtractArchiveFromReader(strings.NewReader(content), "xigmanas.txt")
	if err != nil {
		t.Fatalf("extract txt from reader: %v", err)
	}
	if len(files) != 1 {
		t.Fatalf("expected 1 file, got %d", len(files))
	}
	if files[0].Path != "xigmanas.txt" {
		t.Fatalf("expected filename xigmanas.txt, got %q", files[0].Path)
	}
	if string(files[0].Content) != content {
		t.Fatalf("content mismatch")
	}
}

func TestExtractArchiveTXT(t *testing.T) {
	dir := t.TempDir()
	path := filepath.Join(dir, "sample.txt")
	want := "plain text log"
	if err := os.WriteFile(path, []byte(want), 0o600); err != nil {
		t.Fatalf("write sample txt: %v", err)
	}

	files, err := ExtractArchive(path)
	if err != nil {
		t.Fatalf("extract txt file: %v", err)
	}
	if len(files) != 1 {
		t.Fatalf("expected 1 file, got %d", len(files))
	}
	if files[0].Path != "sample.txt" {
		t.Fatalf("expected sample.txt, got %q", files[0].Path)
	}
	if string(files[0].Content) != want {
		t.Fatalf("content mismatch")
	}
}

func TestExtractArchiveFromReaderTXT_TruncatedWhenTooLarge(t *testing.T) {
	large := bytes.Repeat([]byte("a"), maxSingleFileSize+1024)
	files, err := ExtractArchiveFromReader(bytes.NewReader(large), "huge.log")
	if err != nil {
		t.Fatalf("extract huge txt from reader: %v", err)
	}
	if len(files) != 1 {
		t.Fatalf("expected 1 file, got %d", len(files))
	}

	f := files[0]
	if !f.Truncated {
		t.Fatalf("expected file to be marked as truncated")
	}
	if got := len(f.Content); got != maxSingleFileSize {
		t.Fatalf("expected truncated size %d, got %d", maxSingleFileSize, got)
	}
	if f.TruncatedMessage == "" {
		t.Fatalf("expected truncation message")
	}
}

func TestIsSupportedArchiveFilename(t *testing.T) {
	cases := []struct {
		name string
		want bool
	}{
		{name: "HPE_CZ2D1X0GS3_20260330.ahs", want: true},
		{name: "dump.tar.gz", want: true},
		{name: "nvidia-bug-report-1651124000923.log.gz", want: true},
		{name: "snapshot.zip", want: true},
		{name: "h3c_20250819.sds", want: true},
		{name: "report.log", want: true},
		{name: "xigmanas.txt", want: true},
		{name: "raw_export.json", want: false},
		{name: "archive.bin", want: false},
	}

	for _, tc := range cases {
		got := IsSupportedArchiveFilename(tc.name)
		if got != tc.want {
			t.Fatalf("IsSupportedArchiveFilename(%q)=%v, want %v", tc.name, got, tc.want)
		}
	}
}

func TestExtractArchiveFromReaderSDS(t *testing.T) {
	var buf bytes.Buffer
	tw := tar.NewWriter(&buf)

	payload := []byte("STARTTIME:0\nENDTIME:0\n")
	if err := tw.WriteHeader(&tar.Header{
		Name: "bmc/pack.info",
		Mode: 0o600,
		Size: int64(len(payload)),
	}); err != nil {
		t.Fatalf("write tar header: %v", err)
	}
	if _, err := tw.Write(payload); err != nil {
		t.Fatalf("write tar payload: %v", err)
	}
	if err := tw.Close(); err != nil {
		t.Fatalf("close tar writer: %v", err)
	}

	files, err := ExtractArchiveFromReader(bytes.NewReader(buf.Bytes()), "sample.sds")
	if err != nil {
		t.Fatalf("extract sds from reader: %v", err)
	}
	if len(files) != 1 {
		t.Fatalf("expected 1 extracted file, got %d", len(files))
	}
	if files[0].Path != "bmc/pack.info" {
		t.Fatalf("expected bmc/pack.info, got %q", files[0].Path)
	}
}

func TestExtractArchiveFromReaderAHS(t *testing.T) {
	payload := []byte("ABJRtest")
	files, err := ExtractArchiveFromReader(bytes.NewReader(payload), "sample.ahs")
	if err != nil {
		t.Fatalf("extract ahs from reader: %v", err)
	}
	if len(files) != 1 {
		t.Fatalf("expected 1 extracted file, got %d", len(files))
	}
	if files[0].Path != "sample.ahs" {
		t.Fatalf("expected sample.ahs, got %q", files[0].Path)
	}
	if string(files[0].Content) != string(payload) {
		t.Fatalf("content mismatch")
	}
}
