package nar

import (
	"bytes"
	"encoding/hex"
	"io"
	"testing"

	"github.com/google/go-cmp/cmp"
)

func TestHeader(t *testing.T) {
	var b bytes.Buffer

	sw := serializeWriter{&b}
	wrote, err := sw.WriteString("nix-archive-1")
	if err != nil {
		t.Fatalf("WriteString: %v", err)
	}
	if want := int64(0x18); wrote != want {
		t.Errorf("wrote = 0x%x; want 0x%x", wrote, want)
	}

	wantBuf := append(append([]byte{
		// Length
		0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	}, []byte("nix-archive-1")...), []byte{
		// Padding
		0x00, 0x00, 0x00,
	}...)
	if diff := cmp.Diff(b.Bytes(), wantBuf); diff != "" {
		t.Errorf("b.Bytes() diff (-got +want):\n%s", diff)
	}

	t.Logf("\n%s", hex.Dump(b.Bytes()))
}

func TestPack(t *testing.T) {
	fs := DirFS("testdata")

	for _, tc := range []struct {
		f      string
		golden string
	}{{
		f:      "f.txt",
		golden: "f.txt.nar",
	}, {
		f:      "dir",
		golden: "dir.nar",
	}, {
		f:      "dirWithBadSymlink",
		golden: "dirWithBadSymlink.nar",
	}} {
		t.Run(tc.f, func(t *testing.T) {
			var b bytes.Buffer
			wrote, err := Pack(&b, fs, tc.f)
			if err != nil {
				t.Fatalf("Pack: %v", err)
			}

			golden, err := fs.Open(tc.golden)
			if err != nil {
				t.Fatalf("opening golden %v: %v", tc.golden, err)
			}
			defer golden.Close()
			want, err := io.ReadAll(golden)
			if err != nil {
				t.Fatalf("reading golden %v: %v", tc.golden, err)
			}

			if wrote != int64(len(b.Bytes())) {
				t.Errorf("wrote (%d) != len(b.Bytes()) (%d)", wrote, int64(len(b.Bytes())))
			}
			if diff := cmp.Diff(b.Bytes(), want); diff != "" {
				t.Errorf("b.Bytes() diff (-got +want):\n%s", diff)
			}
		})
	}
}