package blueprint

import "testing"

func TestNormalizeIdent(t *testing.T) {
	cases := map[string]string{
		"beforeDay":              "before_day",
		"cjl.value":              "cjl_value",
		"nextDay":                "next_day",
		"settlement-observation": "settlement_observation",
		"Already_ok":             "already_ok",
	}
	for in, want := range cases {
		got := NormalizeIdent(in)
		if got != want {
			t.Fatalf("%s => %s, want %s", in, got, want)
		}
	}
}

func TestAssignSchemaNameKeepsLongSlugsDistinct(t *testing.T) {
	prefix := "module_with_a_very_long_shared_slug_prefix_that_used_to_collide_"
	a := &Blueprint{Meta: Meta{Slug: prefix + "a"}, Storage: Storage{Mode: "schema_per_app"}}
	b := &Blueprint{Meta: Meta{Slug: prefix + "b"}, Storage: Storage{Mode: "schema_per_app"}}

	gotA := a.AssignSchemaName(12)
	gotB := b.AssignSchemaName(12)
	if gotA == gotB {
		t.Fatalf("different slugs resolved to the same schema: %q", gotA)
	}
	if len(gotA) > 48 || len(gotB) > 48 {
		t.Fatalf("schema names exceed identifier limit: %q / %q", gotA, gotB)
	}
	if gotA != a.AssignSchemaName(12) {
		t.Fatalf("schema name is not deterministic: %q", gotA)
	}
}

func TestRevisionChangesWithSlug(t *testing.T) {
	a := &Blueprint{Version: "1.0", Meta: Meta{Slug: "whm1"}}
	b := &Blueprint{Version: "1.0", Meta: Meta{Slug: "whm11"}}
	if a.Revision() == "" || a.Revision() == b.Revision() {
		t.Fatalf("revision must include blueprint slug: %q / %q", a.Revision(), b.Revision())
	}
}

func TestSanitizeFields(t *testing.T) {
	bp := &Blueprint{
		Version: "1.0",
		Meta:    Meta{Name: "t", Slug: "demo_app", Locale: "zh-CN"},
		Storage: Storage{Mode: "schema_per_app", Engine: "postgres"},
		Entities: []Entity{{
			Name: "Point", Table: "Point", PrimaryKey: "id", Label: "p",
			Fields: []Field{
				{Name: "id", Label: "ID", Type: "bigint"},
				{Name: "beforeDay", Label: "b", Type: "int"},
				{Name: "cjl.value", Label: "v", Type: "decimal"},
			},
		}},
		Apis: Apis{Resources: []APIResource{{
			Entity: "Point", Path: "/Points", Operations: []string{"list"},
			List: &ListOpt{AllowedFilters: []string{"beforeDay"}},
		}}},
		Pages: []Page{{
			ID: "l", Title: "list", Route: "/x", Type: "list", Entity: "Point",
			Layout: &PageLayout{Columns: []string{"beforeDay", "cjl.value"}, Filters: []string{"beforeDay"}},
		}},
	}
	if err := bp.Validate("demo_app"); err != nil {
		t.Fatal(err)
	}
	if bp.Entities[0].Fields[1].Name != "before_day" {
		t.Fatalf("field=%s", bp.Entities[0].Fields[1].Name)
	}
	if bp.Pages[0].Layout.Columns[0] != "before_day" {
		t.Fatalf("col=%v", bp.Pages[0].Layout.Columns)
	}
}
