package catalognamespaceauthority

import (
	"context"
	"regexp"
	"strings"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
)

func TestSchemaDefendsClosedAuthorityShapes(t *testing.T) {
	joined := strings.Join(SchemaStatementsForTest(), "\n")
	required := []string{
		"NamespaceId VARBINARY(128) PRIMARY KEY",
		"OwnerKind VARBINARY(8) NOT NULL",
		"OwnerId VARBINARY(128) NOT NULL",
		"State VARBINARY(16) NOT NULL",
		"TenantSequenceUpperBound DECIMAL(20,0) NULL",
		"OwnerKind = 'SYSTEM'",
		"OwnerKind = 'APP'",
		"OwnerKind = 'TENANT'",
		"OwnerId = NamespaceId",
		"NamespaceId <> '" + SystemNamespace + "'",
		"State IN ('ACTIVE','TOMBSTONE')",
		"TenantSequenceUpperBound >= 0",
		"'" + SystemNamespace + "', 'SYSTEM', '" + SystemNamespace + "', 'ACTIVE', NULL",
	}
	for _, fragment := range required {
		if !strings.Contains(joined, fragment) {
			t.Fatalf("namespace authority schema lacks %q", fragment)
		}
	}
}

func TestEnsureSchemaCreatesLedgerThenSeedsSystemOwner(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatal(err)
	}
	defer db.Close()
	for _, statement := range SchemaStatementsForTest() {
		mock.ExpectExec(regexp.QuoteMeta(statement)).
			WillReturnResult(sqlmock.NewResult(0, 1))
	}
	if err := EnsureSchema(context.Background(), db); err != nil {
		t.Fatalf("EnsureSchema() error = %v", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatal(err)
	}
}

func TestEnsureSchemaRequiresDatabase(t *testing.T) {
	if err := EnsureSchema(context.Background(), nil); err == nil {
		t.Fatal("EnsureSchema() succeeded without a database")
	}
}

func TestSchemaStatementsForTestReturnsDefensiveCopy(t *testing.T) {
	first := SchemaStatementsForTest()
	first[0] = "mutated"
	second := SchemaStatementsForTest()
	if second[0] == "mutated" {
		t.Fatal("SchemaStatementsForTest returned shared storage")
	}
}
