package bootstrapimpl

import (
	"testing"

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

func TestConnectorPushDurableSystemTables(t *testing.T) {
	defs := GetManagedTableDefinitions()

	for tableName, want := range map[string]struct {
		columns      []string
		indexColumns map[string][]string
		columnTypes  map[string]string
	}{
		"_System_ConnectorRemoteLink": {
			columns: []string{
				"Id", "LinkKey", "Status", "RemoteId", "RemoteLocatorHash", "RemoteLocatorActiveKey",
				"ConnectorOwnerKey", "ActionSlotId", "ActionType", "SourceObject", "SourceRecordId",
				"DestinationSlotId", "RequesterOwnerPack", "ProfileOwnerPack", "ConnectorNamespace",
				"TargetObject", "ProfileName", "CreatedPackInstallId", "LastValidatedPackInstallId",
				"CredentialRef", "EndpointClass", "RetryPolicy", "ProfileContractHash", "CreatePathTemplate", "UpdatePathTemplate",
				"ResponseIdPath", "RemoteIdField", "RemoteIdProvenanceField", "MappingFingerprint",
				"BodyFingerprint", "CompatibilityMirrorStatus",
			},
			indexColumns: map[string][]string{
				"uniq_connector_remote_link_key":       {"LinkKey"},
				"uniq_connector_remote_locator_active": {"RemoteLocatorActiveKey"},
				"idx_connector_remote_link_source":     {"SourceObject", "SourceRecordId"},
			},
		},
		"_System_ConnectorPushAttempt": {
			columns: []string{
				"Id", "LinkKey", "AttemptOccupancyKey", "Status", "AttemptOrdinal", "RemoteId", "ConnectorOwnerKey", "ActionSlotId", "ActionType", "SourceObject", "SourceRecordId", "DestinationSlotId",
				"RequesterOwnerPack", "ProfileOwnerPack", "ConnectorNamespace", "TargetObject", "ProfileName", "CreatedPackInstallId", "CredentialRef", "EndpointClass", "RetryPolicy", "ProfileContractHash", "CreatePathTemplate", "UpdatePathTemplate", "ResponseIdPath", "RemoteIdField",
				"RemoteIdProvenanceField", "RemoteIdMirrorExpectedValue", "RemoteIdMirrorCurrentValue", "RemoteIdProvenanceMirrorExpectedValue", "RemoteIdProvenanceMirrorCurrentValue", "MappingFingerprint", "BodyFingerprint", "OriginatingUserId", "OriginatingUserSessionJSON",
				"AllowedSourceFieldsJSON", "RequestIdempotencyKey", "RequestMethod", "RequestRelativePath", "RequestHeaders", "RequestBodyBase64", "RequestBodyHash", "ResponseStatusCode", "ResponseHeaders", "ResponseBodyBase64", "ResponseBodyHash", "CompatibilityMirrorStatus",
				"RetryCount", "LastError", "LastErrorAt", "ClaimedBy", "ClaimToken", "ClaimedAt", "LeaseExpiresAt", "SupersededByAttemptId", "SupersededAt",
			},
			indexColumns: map[string][]string{
				"uniq_connector_push_attempt_occupancy":   {"AttemptOccupancyKey"},
				"uniq_connector_push_attempt_ordinal":     {"LinkKey", "AttemptOrdinal"},
				"uniq_connector_push_attempt_idempotency": {"RequestIdempotencyKey"},
				"idx_connector_push_attempt_gate":         {"LinkKey", "Status"},
				"idx_connector_push_attempt_claim":        {"Status", "ClaimedAt", "CreatedDate"},
			},
			columnTypes: map[string]string{
				"RequestBodyBase64":           "LONGTEXT",
				"ResponseBodyBase64":          "LONGTEXT",
				"RetryPolicy":                 "LONGTEXT",
				"RemoteIdMirrorExpectedValue": "LONGTEXT",
			},
		},
	} {
		def, ok := findConnectorPushSystemTableForTest(defs, tableName)
		if !ok {
			t.Fatalf("%s not found in system_tables.json", tableName)
		}
		if def.TableType != "system_core" {
			t.Fatalf("%s.tableType = %q, want system_core", tableName, def.TableType)
		}
		if def.Category != "integration" {
			t.Fatalf("%s.category = %q, want integration", tableName, def.Category)
		}
		if def.RequiredReadPermission != "BLOCKED" || def.RequiredWritePermission != "BLOCKED" {
			t.Fatalf("%s permissions = %q/%q, want BLOCKED/BLOCKED", tableName, def.RequiredReadPermission, def.RequiredWritePermission)
		}

		columns := make(map[string]schema.ColumnDefinition, len(def.Columns))
		for _, col := range def.Columns {
			columns[col.Name] = col
		}
		for _, col := range want.columns {
			if _, ok := columns[col]; !ok {
				t.Fatalf("%s missing column %s", tableName, col)
			}
		}
		for col, sqlType := range want.columnTypes {
			if got := columns[col].Type; got != sqlType {
				t.Fatalf("%s.%s type = %q, want %q", tableName, col, got, sqlType)
			}
		}

		indexes := make(map[string]schema.IndexDefinition, len(def.Indices))
		for _, idx := range def.Indices {
			indexes[idx.Name] = idx
		}
		for name, cols := range want.indexColumns {
			idx, ok := indexes[name]
			if !ok {
				t.Fatalf("%s missing index %s", tableName, name)
			}
			if !idx.Unique && name[:4] == "uniq" {
				t.Fatalf("%s.%s unique = false, want true", tableName, name)
			}
			if !sameConnectorPushStrings(idx.Columns, cols) {
				t.Fatalf("%s.%s columns = %v, want %v", tableName, name, idx.Columns, cols)
			}
		}
	}
}

func findConnectorPushSystemTableForTest(defs []schema.TableDefinition, tableName string) (schema.TableDefinition, bool) {
	for _, def := range defs {
		if def.TableName == tableName {
			return def, true
		}
	}
	return schema.TableDefinition{}, false
}

func sameConnectorPushStrings(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}
