package bootstrapimpl

import (
	"context"
	"errors"
	"reflect"
	"strings"
	"testing"

	"github.com/nexuscrm/kernel/pkg/schema"
)

type recordingManagedPhysicalTableCreator struct {
	created []schema.TableDefinition
	failOn  string
	err     error
}

func (c *recordingManagedPhysicalTableCreator) CreatePhysicalTable(
	_ context.Context,
	definition schema.TableDefinition,
) error {
	c.created = append(c.created, definition)
	if strings.EqualFold(definition.TableName, c.failOn) {
		return c.err
	}
	return nil
}

func TestReconcileConnectorV2IngressReceiptAuthorityTablesReplaysExactCatalogParentThenChild(t *testing.T) {
	tableDefs := GetManagedTableDefinitions()
	want, err := connectorV2IngressReceiptAuthorityDefinitionsFrom(tableDefs)
	if err != nil {
		t.Fatalf("resolve exact authority definitions: %v", err)
	}
	creator := &recordingManagedPhysicalTableCreator{}

	if err := reconcileConnectorV2IngressReceiptAuthorityTables(context.Background(), creator, tableDefs); err != nil {
		t.Fatalf("reconcile V2 ingress receipt authority tables: %v", err)
	}
	if !reflect.DeepEqual(creator.created, want) {
		t.Fatalf("created definitions = %#v, want exact parent-then-child catalog definitions %#v", creator.created, want)
	}
	if len(creator.created) != 3 {
		t.Fatalf("created definitions = %d, want 3", len(creator.created))
	}
	if creator.created[0].TableName != "_System_ConnectorV2Receipt" ||
		creator.created[1].TableName != "_System_ConnectorV2ReceiptComponent" ||
		creator.created[2].TableName != "_System_ConnectorV2ReceiptAdmissionKey" {
		t.Fatalf("creation order = %v, want receipt parent then component and admission-key children", []string{
			creator.created[0].TableName,
			creator.created[1].TableName,
			creator.created[2].TableName,
		})
	}
}

func TestReconcileConnectorV2IngressReceiptAuthorityTablesRejectsCatalogAmbiguityBeforeMutation(t *testing.T) {
	tableDefs := GetManagedTableDefinitions()
	withoutChild := make([]schema.TableDefinition, 0, len(tableDefs))
	for _, definition := range tableDefs {
		if definition.TableName != "_System_ConnectorV2ReceiptAdmissionKey" {
			withoutChild = append(withoutChild, definition)
		}
	}
	creator := &recordingManagedPhysicalTableCreator{}

	err := reconcileConnectorV2IngressReceiptAuthorityTables(context.Background(), creator, withoutChild)
	if err == nil || !strings.Contains(err.Error(), "_System_ConnectorV2ReceiptAdmissionKey") || !strings.Contains(err.Error(), "found 0") {
		t.Fatalf("missing child catalog error = %v, want exact-definition rejection", err)
	}
	if len(creator.created) != 0 {
		t.Fatalf("created definitions after catalog rejection = %d, want 0", len(creator.created))
	}
}

func TestReconcileConnectorV2IngressReceiptAuthorityTablesStopsOnCreationFailure(t *testing.T) {
	sentinel := errors.New("create parent failed")
	creator := &recordingManagedPhysicalTableCreator{
		failOn: "_System_ConnectorV2Receipt",
		err:    sentinel,
	}

	err := reconcileConnectorV2IngressReceiptAuthorityTables(
		context.Background(),
		creator,
		GetManagedTableDefinitions(),
	)
	if !errors.Is(err, sentinel) || !strings.Contains(err.Error(), "_System_ConnectorV2Receipt") {
		t.Fatalf("creation error = %v, want wrapped parent failure", err)
	}
	if len(creator.created) != 1 {
		t.Fatalf("creation attempts = %d, want stop before child", len(creator.created))
	}
}
