package bootstrap

import "testing"

// TestRenderFieldModern locks the v0.23+ ("fields") wire shape for each field
// type against what PocketBase expects.
func TestRenderFieldModern(t *testing.T) {
	idByName := map[string]string{"cars": "col_cars"}

	rel := renderField(fRelation("car", "cars", true, true), "fields", idByName)
	if rel["collectionId"] != "col_cars" || rel["cascadeDelete"] != true ||
		rel["maxSelect"] != 1 || rel["minSelect"] != 0 || rel["required"] != true {
		t.Fatalf("relation rendered wrong: %#v", rel)
	}

	nonCascade := renderField(fRelation("owner", "users", false, false), "fields", map[string]string{"users": "u"})
	if nonCascade["cascadeDelete"] != false {
		t.Fatalf("non-cascading relation should keep cascadeDelete=false: %#v", nonCascade)
	}

	sel := renderField(fSelect("result", []string{"passed", "failed"}, false), "fields", idByName)
	if sel["maxSelect"] != 1 {
		t.Fatalf("select maxSelect: %#v", sel)
	}
	if vals, ok := sel["values"].([]string); !ok || len(vals) != 2 {
		t.Fatalf("select values: %#v", sel["values"])
	}

	ad := renderField(fAutodate("created", true, false), "fields", idByName)
	if ad["onCreate"] != true || ad["onUpdate"] != false {
		t.Fatalf("autodate: %#v", ad)
	}

	file := renderField(attachment(), "fields", idByName)
	if file["maxSize"] != 10485760 || file["maxSelect"] != 1 {
		t.Fatalf("file: %#v", file)
	}
	if mt, ok := file["mimeTypes"].([]string); !ok || len(mt) != 5 {
		t.Fatalf("file mimeTypes: %#v", file["mimeTypes"])
	}

	j := renderField(fJSON("params", 10000), "fields", idByName)
	if j["maxSize"] != 10000 {
		t.Fatalf("json: %#v", j)
	}
}

// TestRenderFieldLegacy checks that the legacy ("schema") layout nests options.
func TestRenderFieldLegacy(t *testing.T) {
	rel := renderField(fRelation("car", "cars", true, true), "schema", map[string]string{"cars": "col_cars"})
	opts, ok := rel["options"].(map[string]any)
	if !ok {
		t.Fatalf("legacy relation should nest options: %#v", rel)
	}
	if opts["collectionId"] != "col_cars" || opts["cascadeDelete"] != true {
		t.Fatalf("legacy relation options: %#v", opts)
	}
}

// TestSameValues covers the select-reconcile comparison (order-insensitive).
func TestSameValues(t *testing.T) {
	if !sameValues([]any{"a", "b"}, []string{"b", "a"}) {
		t.Fatal("same set in different order should compare equal")
	}
	if sameValues([]any{"a"}, []string{"a", "b"}) {
		t.Fatal("differing lengths should not be equal")
	}
	if sameValues([]any{"a", "c"}, []string{"a", "b"}) {
		t.Fatal("differing members should not be equal")
	}
	if sameValues(nil, []string{"a"}) {
		t.Fatal("nil current should not equal non-empty want")
	}
}

// TestSchemaConsistency guards the ordered lists against the schema map.
func TestSchemaConsistency(t *testing.T) {
	for _, name := range createOrder {
		if _, ok := collectionsSchema[name]; !ok {
			t.Errorf("createOrder references unknown collection %q", name)
		}
		if name == "users" {
			t.Errorf("users must not be in createOrder (built-in auth collection)")
		}
	}
	for _, name := range reconcileOrder {
		if _, ok := collectionsSchema[name]; !ok {
			t.Errorf("reconcileOrder references unknown collection %q", name)
		}
	}
	for name := range indexes {
		if _, ok := collectionsSchema[name]; !ok {
			t.Errorf("indexes references unknown collection %q", name)
		}
	}
}
