package catalogd

import (
	"testing"
	"time"
)

func TestEncodeDecode_RoundTrip(t *testing.T) {
	rc := int64(500_000)
	now := time.Unix(1777435000, 123456789)
	want := &Manifest{
		DatasetID:         DatasetIDForName("workers_500k"),
		Name:              "workers_500k",
		SchemaFingerprint: "sha256:abcdef",
		Objects: []Object{
			{Key: "datasets/workers_500k/part-001.parquet", Size: 75 * 1024 * 1024},
			{Key: "datasets/workers_500k/part-002.parquet", Size: 12 * 1024 * 1024},
		},
		CreatedAt: now,
		UpdatedAt: now.Add(time.Minute),
		RowCount:  &rc,
	}

	b, err := Encode(want)
	if err != nil {
		t.Fatalf("Encode: %v", err)
	}
	if len(b) == 0 {
		t.Fatal("Encode returned 0 bytes")
	}

	got, err := Decode(b)
	if err != nil {
		t.Fatalf("Decode: %v", err)
	}

	if got.DatasetID != want.DatasetID {
		t.Errorf("DatasetID: got %q, want %q", got.DatasetID, want.DatasetID)
	}
	if got.Name != want.Name {
		t.Errorf("Name: got %q, want %q", got.Name, want.Name)
	}
	if got.SchemaFingerprint != want.SchemaFingerprint {
		t.Errorf("SchemaFingerprint: got %q, want %q", got.SchemaFingerprint, want.SchemaFingerprint)
	}
	if len(got.Objects) != 2 {
		t.Fatalf("Objects: got %d, want 2", len(got.Objects))
	}
	for i, o := range got.Objects {
		if o.Key != want.Objects[i].Key || o.Size != want.Objects[i].Size {
			t.Errorf("Objects[%d]: got %+v, want %+v", i, o, want.Objects[i])
		}
	}
	// Times round-trip via UnixNano so equality is on the nanosecond.
	if !got.CreatedAt.Equal(want.CreatedAt) {
		t.Errorf("CreatedAt: got %v, want %v", got.CreatedAt, want.CreatedAt)
	}
	if !got.UpdatedAt.Equal(want.UpdatedAt) {
		t.Errorf("UpdatedAt: got %v, want %v", got.UpdatedAt, want.UpdatedAt)
	}
	if got.RowCount == nil || *got.RowCount != *want.RowCount {
		t.Errorf("RowCount: got %v, want %v", got.RowCount, want.RowCount)
	}
}

func TestEncodeDecode_NoRowCount(t *testing.T) {
	want := &Manifest{
		DatasetID:         DatasetIDForName("unknown_size"),
		Name:              "unknown_size",
		SchemaFingerprint: "sha256:zero",
		Objects:           []Object{},
		CreatedAt:         time.Unix(0, 0),
		UpdatedAt:         time.Unix(0, 0),
		RowCount:          nil,
	}

	b, err := Encode(want)
	if err != nil {
		t.Fatal(err)
	}
	got, err := Decode(b)
	if err != nil {
		t.Fatal(err)
	}
	if got.RowCount != nil {
		t.Errorf("RowCount: got %v, want nil", got.RowCount)
	}
	if len(got.Objects) != 0 {
		t.Errorf("Objects: got %d, want 0", len(got.Objects))
	}
}

func TestDatasetIDForName_Deterministic(t *testing.T) {
	a := DatasetIDForName("workers_500k")
	b := DatasetIDForName("workers_500k")
	if a != b {
		t.Errorf("DatasetIDForName not deterministic: %q vs %q", a, b)
	}
	c := DatasetIDForName("different")
	if a == c {
		t.Errorf("DatasetIDForName collided across distinct names")
	}
}
