package main

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

// withWayfarerGalaxySeed временно подставляет seed и гарантированно
// возвращает прежнее значение после теста — иначе один тест мог бы
// незаметно повлиять на данные систем в других тестах пакета.
func withWayfarerGalaxySeed(t *testing.T, seed uint64) {
	t.Helper()
	old := wayfarerGalaxySeed
	wayfarerGalaxySeed = seed
	t.Cleanup(func() { wayfarerGalaxySeed = old })
}

func TestDefaultGalaxySeedMatchesUnmodifiedHash(t *testing.T) {
	withWayfarerGalaxySeed(t, 0)
	id := WayfarerSystemID{Galaxy: 2, Index: 17}
	got := systemSeed(id)

	x := uint64(id.Galaxy)*1000003 + uint64(id.Index) + 0x9E3779B97F4A7C15
	x = (x ^ (x >> 30)) * 0xBF58476D1CE4E5B9
	x = (x ^ (x >> 27)) * 0x94D049BB133111EB
	x = x ^ (x >> 31)
	want := int64(x)

	if got != want {
		t.Errorf("нулевой сид должен давать точно такой же хэш, как без учёта сида вовсе: got=%d want=%d", got, want)
	}
}

func TestDifferentGalaxySeedProducesDifferentSystem(t *testing.T) {
	id := WayfarerSystemID{Galaxy: 0, Index: 0}

	withWayfarerGalaxySeed(t, 0)
	base := GenerateSystem(id)

	withWayfarerGalaxySeed(t, 424242)
	changed := GenerateSystem(id)

	if base.Name == changed.Name && base.X == changed.X && base.Y == changed.Y &&
		base.Government == changed.Government && base.TechLevel == changed.TechLevel {
		t.Errorf("другой сид галактики должен был дать другую систему для того же ID")
	}
}

func TestGalaxySeedStillDeterministicWithinItself(t *testing.T) {
	withWayfarerGalaxySeed(t, 555)
	id := WayfarerSystemID{Galaxy: 3, Index: 100}
	a := GenerateSystem(id)
	b := GenerateSystem(id)
	if a != b {
		t.Errorf("при одном и том же (сид + ID) система должна оставаться детерминированной")
	}
}

func TestReadWayfarerSeedFromEnvFileValid(t *testing.T) {
	dir := t.TempDir()
	path := filepath.Join(dir, ".env")
	os.WriteFile(path, []byte("SOME_OTHER_VAR=1\nWAYFARER_GALAXY_SEED=777\n"), 0o644)

	seed, ok := readWayfarerSeedFromEnvFile(path)
	if !ok || seed != 777 {
		t.Fatalf("ожидался сид 777, получено %d (ok=%v)", seed, ok)
	}
}

func TestReadWayfarerSeedFromEnvFileMissingFile(t *testing.T) {
	_, ok := readWayfarerSeedFromEnvFile(filepath.Join(t.TempDir(), "nope.env"))
	if ok {
		t.Errorf("отсутствующий файл должен давать ok=false")
	}
}

func TestReadWayfarerSeedFromEnvFileNoMatchingKey(t *testing.T) {
	dir := t.TempDir()
	path := filepath.Join(dir, ".env")
	os.WriteFile(path, []byte("FOO=1\nBAR=2\n"), 0o644)

	_, ok := readWayfarerSeedFromEnvFile(path)
	if ok {
		t.Errorf("файл без нужного ключа должен давать ok=false")
	}
}

func TestReadWayfarerSeedFromEnvFileIgnoresCommentsAndBlankLines(t *testing.T) {
	dir := t.TempDir()
	path := filepath.Join(dir, ".env")
	os.WriteFile(path, []byte("# комментарий\n\n   \nWAYFARER_GALAXY_SEED=99\n"), 0o644)

	seed, ok := readWayfarerSeedFromEnvFile(path)
	if !ok || seed != 99 {
		t.Fatalf("ожидался сид 99, получено %d (ok=%v)", seed, ok)
	}
}

func TestReadWayfarerSeedFromEnvFileHandlesQuotesAndSpaces(t *testing.T) {
	dir := t.TempDir()
	path := filepath.Join(dir, ".env")
	os.WriteFile(path, []byte(`WAYFARER_GALAXY_SEED = "12345"`+"\n"), 0o644)

	seed, ok := readWayfarerSeedFromEnvFile(path)
	if !ok || seed != 12345 {
		t.Fatalf("ожидался сид 12345 с учётом пробелов/кавычек, получено %d (ok=%v)", seed, ok)
	}
}

func TestReadWayfarerSeedFromEnvFileNegativeNumber(t *testing.T) {
	dir := t.TempDir()
	path := filepath.Join(dir, ".env")
	os.WriteFile(path, []byte("WAYFARER_GALAXY_SEED=-5\n"), 0o644)

	_, ok := readWayfarerSeedFromEnvFile(path)
	if !ok {
		t.Errorf("отрицательное число должно успешно парситься (и просто давать другой битовый узор сида)")
	}
}

func TestReadWayfarerSeedFromEnvFileMalformedValue(t *testing.T) {
	dir := t.TempDir()
	path := filepath.Join(dir, ".env")
	os.WriteFile(path, []byte("WAYFARER_GALAXY_SEED=not-a-number\n"), 0o644)

	_, ok := readWayfarerSeedFromEnvFile(path)
	if ok {
		t.Errorf("нечисловое значение должно давать ok=false")
	}
}

func TestLoadWayfarerGalaxySeedNoFileLeavesDefault(t *testing.T) {
	dir := t.TempDir()
	oldWd, _ := os.Getwd()
	os.Chdir(dir)
	defer os.Chdir(oldWd)

	defer func() { wayfarerGalaxySeed = 0 }()
	wayfarerGalaxySeed = 0
	loadWayfarerGalaxySeed()
	if wayfarerGalaxySeed != 0 {
		t.Errorf("без файла .env сид должен остаться нулевым, получено %d", wayfarerGalaxySeed)
	}
}

func TestLoadWayfarerGalaxySeedFromCWD(t *testing.T) {
	dir := t.TempDir()
	os.WriteFile(filepath.Join(dir, ".env"), []byte("WAYFARER_GALAXY_SEED=42\n"), 0o644)
	oldWd, _ := os.Getwd()
	os.Chdir(dir)
	defer os.Chdir(oldWd)

	defer func() { wayfarerGalaxySeed = 0 }()
	wayfarerGalaxySeed = 0
	loadWayfarerGalaxySeed()
	if wayfarerGalaxySeed != 42 {
		t.Errorf("ожидался сид 42, загруженный из .env в текущей директории, получено %d", wayfarerGalaxySeed)
	}
}
