package bootstrapimpl

import (
	"regexp"
	"strings"
	"testing"

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

func TestVerifyPackGenerationAuthorityIndexesAcceptsExactUniqueShape(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock.New: %v", err)
	}
	defer db.Close()

	expectPackGenerationAuthorityIndex(
		mock,
		"_System_PackGeneration",
		"uq_pack_generation_install",
		0,
		[]string{"PackInstallId"},
	)
	expectPackGenerationAuthorityIndex(
		mock,
		"_System_PackActivation",
		"uq_pack_activation_name",
		0,
		[]string{"PackName"},
	)
	expectPackGenerationAuthorityIndex(
		mock,
		"_System_PackGenerationConnectorBindingDefinitionSet",
		"PRIMARY",
		0,
		[]string{"PackGenerationId"},
	)
	expectPackGenerationAuthorityIndex(
		mock,
		"_System_PackGenerationConnectorBindingDefinition",
		"PRIMARY",
		0,
		[]string{"Id"},
	)
	expectPackGenerationAuthorityIndex(
		mock,
		"_System_PackGenerationConnectorBindingDefinition",
		"ux_pack_generation_binding_definition_ordinal",
		0,
		[]string{"PackGenerationId", "DefinitionOrdinal"},
	)
	expectPackGenerationAuthorityIndex(
		mock,
		"_System_PackGenerationConnectorBindingDefinition",
		"ux_pack_generation_binding_definition_identity",
		0,
		[]string{"PackGenerationId", "Kind", "BusinessKey"},
	)

	if err := verifyPackGenerationAuthorityIndexes(db); err != nil {
		t.Fatalf("verifyPackGenerationAuthorityIndexes: %v", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("SQL expectations: %v", err)
	}
}

func TestVerifyPackGenerationAuthorityIndexesRejectsMissingDefinitionPrimaryKey(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock.New: %v", err)
	}
	defer db.Close()

	expectPackGenerationAuthorityIndex(
		mock,
		"_System_PackGeneration",
		"uq_pack_generation_install",
		0,
		[]string{"PackInstallId"},
	)
	expectPackGenerationAuthorityIndex(
		mock,
		"_System_PackActivation",
		"uq_pack_activation_name",
		0,
		[]string{"PackName"},
	)
	expectPackGenerationAuthorityIndex(
		mock,
		"_System_PackGenerationConnectorBindingDefinitionSet",
		"PRIMARY",
		0,
		[]string{"PackGenerationId"},
	)
	expectPackGenerationAuthorityIndex(
		mock,
		"_System_PackGenerationConnectorBindingDefinition",
		"PRIMARY",
		0,
		nil,
	)

	err = verifyPackGenerationAuthorityIndexes(db)
	if err == nil ||
		!strings.Contains(err.Error(), "_System_PackGenerationConnectorBindingDefinition.PRIMARY(Id)") ||
		!strings.Contains(err.Error(), "cmd/setup apply") {
		t.Fatalf("missing definition primary-key readiness error = %v", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("SQL expectations: %v", err)
	}
}

func TestVerifyPackGenerationAuthorityIndexesRejectsNonUniqueShape(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock.New: %v", err)
	}
	defer db.Close()

	expectPackGenerationAuthorityIndex(
		mock,
		"_System_PackGeneration",
		"uq_pack_generation_install",
		1,
		[]string{"PackInstallId"},
	)

	err = verifyPackGenerationAuthorityIndexes(db)
	if err == nil ||
		!strings.Contains(err.Error(), "_System_PackGeneration.uq_pack_generation_install") ||
		!strings.Contains(err.Error(), "cmd/setup apply") {
		t.Fatalf("non-unique readiness error = %v, want fail-closed reconciliation guidance", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("SQL expectations: %v", err)
	}
}

func TestVerifyPackGenerationAuthorityIndexesRejectsUniquePrefixIndex(t *testing.T) {
	db, mock, err := sqlmock.New()
	if err != nil {
		t.Fatalf("sqlmock.New: %v", err)
	}
	defer db.Close()

	// The scoped inspection returns SUB_PART; the shared verifier rejects
	// prefix indexes rather than filtering them out in a schema-wide subquery.
	mock.ExpectQuery(regexp.QuoteMeta("SELECT NON_UNIQUE, SEQ_IN_INDEX, COLUMN_NAME, SUB_PART")).
		WithArgs("_System_PackGeneration", "uq_pack_generation_install").
		WillReturnRows(sqlmock.NewRows([]string{"NON_UNIQUE", "SEQ_IN_INDEX", "COLUMN_NAME", "SUB_PART"}).
			AddRow(0, 1, "PackInstallId", 16))

	err = verifyPackGenerationAuthorityIndexes(db)
	if err == nil ||
		!strings.Contains(err.Error(), "_System_PackGeneration.uq_pack_generation_install") ||
		!strings.Contains(err.Error(), "full-column unique index") {
		t.Fatalf("prefix-index readiness error = %v, want fail-closed full-column requirement", err)
	}
	if err := mock.ExpectationsWereMet(); err != nil {
		t.Fatalf("SQL expectations: %v", err)
	}
}

func expectPackGenerationAuthorityIndex(
	mock sqlmock.Sqlmock,
	tableName string,
	indexName string,
	nonUnique int,
	columns []string,
) {
	rows := sqlmock.NewRows([]string{"NON_UNIQUE", "SEQ_IN_INDEX", "COLUMN_NAME", "SUB_PART"})
	for position, column := range columns {
		rows.AddRow(nonUnique, position+1, column, nil)
	}
	mock.ExpectQuery(regexp.QuoteMeta("SELECT NON_UNIQUE, SEQ_IN_INDEX, COLUMN_NAME, SUB_PART")).
		WithArgs(tableName, indexName).
		WillReturnRows(rows)
}
