package persistence

import (
	"errors"
	"strings"
	"testing"

	apperrors "github.com/nexuscrm/kernel/pkg/errors"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
)

func protectedCascadeParentAliasSchema() *models.ObjectMetadata {
	return &models.ObjectMetadata{
		APIName: "ObjectMetadata",
		ReadSource: &models.ObjectReadSourceConfig{
			Kind:          "physical_table",
			PhysicalTable: constants.TableObject,
		},
	}
}

func TestRejectGenericProtectedCascadeParentRemovalResolvesCanonicalParents(t *testing.T) {
	for _, testCase := range []struct {
		name      string
		tableName string
		schema    *models.ObjectMetadata
	}{
		{
			name:      "physical table",
			tableName: constants.TableObject,
		},
		{
			name:      "case folded physical table",
			tableName: strings.ToLower(constants.TableObject),
		},
		{
			name:      "logical read source alias",
			tableName: "ObjectMetadata",
			schema:    protectedCascadeParentAliasSchema(),
		},
	} {
		t.Run(testCase.name, func(t *testing.T) {
			err := RejectGenericProtectedCascadeParentRemoval(
				testCase.tableName,
				testCase.schema,
			)
			var validationErr *apperrors.ValidationError
			if !errors.As(err, &validationErr) {
				t.Fatalf("error = %T %v, want *errors.ValidationError", err, err)
			}
			if !strings.Contains(err.Error(), constants.TableRecordType) {
				t.Fatalf("error = %v, want protected child %s", err, constants.TableRecordType)
			}
		})
	}
}

func TestRejectGenericProtectedCascadeParentRemovalAllowsUnrelatedTable(t *testing.T) {
	if err := RejectGenericProtectedCascadeParentRemoval(
		"Account",
		&models.ObjectMetadata{APIName: "Account"},
	); err != nil {
		t.Fatalf("ordinary table rejected: %v", err)
	}
}

func TestRejectGenericProtectedCascadeParentRemovalFailsClosedOnMalformedAlias(t *testing.T) {
	err := RejectGenericProtectedCascadeParentRemoval(
		"ObjectMetadata",
		&models.ObjectMetadata{
			APIName: "ObjectMetadata",
			ReadSource: &models.ObjectReadSourceConfig{
				Kind:          "view",
				PhysicalTable: constants.TableObject,
			},
		},
	)
	var internalErr *apperrors.InternalError
	if !errors.As(err, &internalErr) {
		t.Fatalf("error = %T %v, want *errors.InternalError", err, err)
	}
}
