package persistence

import (
	"context"
	"errors"
	"testing"

	"github.com/DATA-DOG/go-sqlmock"
	"github.com/nexuscrm/backend/internal/domain/schema"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/stretchr/testify/require"
)

func safetyTestTableDef(tableName string) schema.TableDefinition {
	return schema.TableDefinition{
		TableName:   tableName,
		TableType:   "custom_object",
		Category:    "test",
		Description: "safety test table",
		Columns: []schema.ColumnDefinition{
			{
				Name:       "Id",
				Type:       "VARCHAR(36)",
				PrimaryKey: true,
				Nullable:   false,
			},
		},
	}
}

func TestBatchCreatePhysicalTables_PreservesTablesOnRegisterFailure(t *testing.T) {
	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherRegexp))
	require.NoError(t, err)
	defer db.Close()

	repo := NewSchemaRepository(db, nil)
	def := safetyTestTableDef("SafetyBatchTable")

	mock.ExpectExec("SET FOREIGN_KEY_CHECKS=0").
		WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectExec("CREATE TABLE IF NOT EXISTS `SafetyBatchTable`").
		WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectExec("INSERT INTO `_System_Table`").
		WillReturnError(errors.New("register failed"))

	err = repo.BatchCreatePhysicalTables(context.Background(), []schema.TableDefinition{def})
	require.Error(t, err)
	require.Contains(t, err.Error(), "failed to batch register tables")
	require.NoError(t, mock.ExpectationsWereMet())
}

func TestCreateTableWithStrictMetadata_PreservesPhysicalTableOnRegisterFailure(t *testing.T) {
	db, mock, err := sqlmock.New(sqlmock.QueryMatcherOption(sqlmock.QueryMatcherRegexp))
	require.NoError(t, err)
	defer db.Close()

	repo := NewSchemaRepository(db, nil)
	def := safetyTestTableDef("SafetyStrictTable")
	meta := &models.ObjectMetadata{
		APIName: "SafetyStrictTable",
	}

	mock.ExpectExec("SET FOREIGN_KEY_CHECKS=0").
		WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectExec("CREATE TABLE IF NOT EXISTS `SafetyStrictTable`").
		WillReturnResult(sqlmock.NewResult(0, 0))
	mock.ExpectBegin()
	mock.ExpectExec("INSERT INTO `_System_Table`").
		WillReturnError(errors.New("register failed"))
	mock.ExpectRollback()

	err = repo.CreateTableWithStrictMetadata(context.Background(), def, meta)
	require.Error(t, err)
	require.Contains(t, err.Error(), "failed to register table SafetyStrictTable")
	require.NoError(t, mock.ExpectationsWereMet())
}
