package engine

import (
	"os"
	"path/filepath"
	"testing"
)

func TestDeliverVersion(t *testing.T) {
	// A blank seed directory disables delivery (the pre-existing seed-only behaviour).
	if err := DeliverVersion(t.TempDir(), "", "v1.3.1"); err != nil {
		t.Fatalf("blank seedDir: %v", err)
	}

	// An existing volume flat-seeded as v1.3.0 gets v1.3.1 delivered as a subdirectory,
	// add-only: the flat seed's marker is left intact and the new version's DAWGs land.
	dict := t.TempDir()
	seed := t.TempDir()
	if err := os.WriteFile(filepath.Join(dict, seedMarkerFile), []byte("v1.3.0\n"), 0o644); err != nil {
		t.Fatal(err)
	}
	for _, f := range dictFiles {
		if err := os.WriteFile(filepath.Join(seed, f), []byte("dawg:"+f), 0o644); err != nil {
			t.Fatal(err)
		}
	}
	if err := DeliverVersion(dict, seed, "v1.3.1"); err != nil {
		t.Fatalf("deliver v1.3.1: %v", err)
	}
	for _, f := range dictFiles {
		got, err := os.ReadFile(filepath.Join(dict, "v1.3.1", f))
		if err != nil {
			t.Fatalf("delivered %s: %v", f, err)
		}
		if string(got) != "dawg:"+f {
			t.Errorf("delivered %s = %q, want the seed bytes", f, got)
		}
	}
	if m, _ := os.ReadFile(filepath.Join(dict, seedMarkerFile)); string(m) != "v1.3.0\n" {
		t.Errorf("flat seed marker relabelled to %q (delivery must be add-only)", m)
	}
	// Idempotent: a second call is a no-op and leaves no staging directory behind.
	if err := DeliverVersion(dict, seed, "v1.3.1"); err != nil {
		t.Fatalf("re-deliver v1.3.1: %v", err)
	}
	if entries, _ := os.ReadDir(dict); hasStaging(entries) {
		t.Errorf("a staging directory survived delivery")
	}

	// On a fresh directory the build version becomes the flat seed, so nothing is delivered
	// as a redundant subdirectory.
	fresh := t.TempDir()
	if err := DeliverVersion(fresh, seed, "v1.3.1"); err != nil {
		t.Fatalf("fresh deliver: %v", err)
	}
	if _, err := os.Stat(filepath.Join(fresh, "v1.3.1")); !os.IsNotExist(err) {
		t.Errorf("fresh volume got a redundant v1.3.1 subdir; it should be the flat seed")
	}
}

func hasStaging(entries []os.DirEntry) bool {
	for _, e := range entries {
		if len(e.Name()) >= len(".staging") && e.Name()[:len(".staging")] == ".staging" {
			return true
		}
	}
	return false
}
