import { test } from '@japa/runner'
import {
  DataDomain,
  DataDomainKind,
  DomainEntityKind,
  DomainModelKind,
  DomainNamespaceKind,
  DomainEntity,
  Thing,
} from '../../../src/index.js'
import type { EntityOrderedItem } from '../../../src/modeling/DomainEntity.js'
import { SemanticType } from '../../../src/modeling/Semantics.js'

test.group('DomainEntity.createSchema()', () => {
  test('creates a schema with default values', ({ assert }) => {
    const schema = DomainEntity.createSchema()
    assert.equal(schema.kind, DomainEntityKind)
    assert.typeOf(schema.key, 'string')
    assert.isNotEmpty(schema.key)
    assert.deepInclude(schema.info, { name: 'new_entity' })
    assert.isUndefined(schema.tags)
    assert.isUndefined(schema.semantics)
    assert.isUndefined(schema.fields)
    assert.isUndefined(schema.deprecated)
  })

  test('creates a schema with provided values', ({ assert }) => {
    const schema = DomainEntity.createSchema({
      key: 'test-entity',
      info: { name: 'Test Entity', description: 'A test entity' },
      tags: ['tag1', 'tag2'],
      semantics: [{ id: SemanticType.User }],
      fields: [{ key: 'test-property', type: 'property' }],
      deprecated: true,
    })
    assert.equal(schema.kind, DomainEntityKind)
    assert.equal(schema.key, 'test-entity')
    assert.deepInclude(schema.info, { name: 'Test Entity', description: 'A test entity' })
    assert.deepEqual(schema.tags, ['tag1', 'tag2'])
    assert.deepEqual(schema.semantics, [{ id: SemanticType.User }])
    assert.deepEqual(schema.fields, [{ key: 'test-property', type: 'property' }])
    assert.isTrue(schema.deprecated)
  })

  test('creates a schema with partial info', ({ assert }) => {
    const schema = DomainEntity.createSchema({
      info: { name: 'Test Entity' },
    })
    assert.equal(schema.kind, DomainEntityKind)
    assert.typeOf(schema.key, 'string')
    assert.isNotEmpty(schema.key)
    assert.deepInclude(schema.info, { name: 'Test Entity' })
  })

  test('creates a schema with empty info', ({ assert }) => {
    const schema = DomainEntity.createSchema({
      info: {},
    })
    assert.equal(schema.kind, DomainEntityKind)
    assert.typeOf(schema.key, 'string')
    assert.isNotEmpty(schema.key)
    assert.deepInclude(schema.info, { name: 'new_entity' })
  })

  test('creates a schema with tags', ({ assert }) => {
    const schema = DomainEntity.createSchema({
      tags: ['tag1', 'tag2'],
    })
    assert.equal(schema.kind, DomainEntityKind)
    assert.typeOf(schema.key, 'string')
    assert.isNotEmpty(schema.key)
    assert.deepInclude(schema.info, { name: 'new_entity' })
    assert.deepEqual(schema.tags, ['tag1', 'tag2'])
  })

  test('creates a schema with semantics', ({ assert }) => {
    const schema = DomainEntity.createSchema({
      semantics: [{ id: SemanticType.User }],
    })
    assert.equal(schema.kind, DomainEntityKind)
    assert.typeOf(schema.key, 'string')
    assert.isNotEmpty(schema.key)
    assert.deepInclude(schema.info, { name: 'new_entity' })
    assert.deepEqual(schema.semantics, [{ id: SemanticType.User }])
  })

  test('creates a schema with fields', ({ assert }) => {
    const schema = DomainEntity.createSchema({
      fields: [{ key: 'test-property', type: 'property' }],
    })
    assert.equal(schema.kind, DomainEntityKind)
    assert.typeOf(schema.key, 'string')
    assert.isNotEmpty(schema.key)
    assert.deepInclude(schema.info, { name: 'new_entity' })
    assert.deepEqual(schema.fields, [{ key: 'test-property', type: 'property' }])
  })

  test('creates a schema with deprecated set to true', ({ assert }) => {
    const schema = DomainEntity.createSchema({
      deprecated: true,
    })
    assert.equal(schema.kind, DomainEntityKind)
    assert.typeOf(schema.key, 'string')
    assert.isNotEmpty(schema.key)
    assert.deepInclude(schema.info, { name: 'new_entity' })
    assert.isTrue(schema.deprecated)
  })

  test('creates a schema with deprecated set to false', ({ assert }) => {
    const schema = DomainEntity.createSchema({
      deprecated: false,
    })
    assert.equal(schema.kind, DomainEntityKind)
    assert.typeOf(schema.key, 'string')
    assert.isNotEmpty(schema.key)
    assert.deepInclude(schema.info, { name: 'new_entity' })
    assert.isFalse(schema.deprecated)
  })

  test('creates a schema with a custom key', ({ assert }) => {
    const customKey = 'custom-key'
    const schema = DomainEntity.createSchema({ key: customKey })
    assert.equal(schema.key, customKey)
  })

  test('creates a schema with custom info', ({ assert }) => {
    const customInfo = { name: 'Custom Name', description: 'Custom Description' }
    const schema = DomainEntity.createSchema({ info: customInfo })
    assert.deepInclude(schema.info, customInfo)
  })

  test('creates a schema with custom tags', ({ assert }) => {
    const customTags = ['custom-tag1', 'custom-tag2']
    const schema = DomainEntity.createSchema({ tags: customTags })
    assert.deepEqual(schema.tags, customTags)
  })

  test('creates a schema with custom semantics', ({ assert }) => {
    const customSemantics = [{ id: SemanticType.User }]
    const schema = DomainEntity.createSchema({ semantics: customSemantics })
    assert.deepEqual(schema.semantics, customSemantics)
  })

  test('creates a schema with custom fields', ({ assert }) => {
    const customFields: EntityOrderedItem[] = [{ key: 'custom-property', type: 'property' }]
    const schema = DomainEntity.createSchema({ fields: customFields })
    assert.deepEqual(schema.fields, customFields)
  })

  test('creates a schema with custom deprecated value', ({ assert }) => {
    const schemaTrue = DomainEntity.createSchema({ deprecated: true })
    assert.isTrue(schemaTrue.deprecated)

    const schemaFalse = DomainEntity.createSchema({ deprecated: false })
    assert.isFalse(schemaFalse.deprecated)
  })
})

test.group('DomainEntity.constructor()', () => {
  test('creates a new DomainEntity with default values', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain)
    assert.equal(entity.kind, DomainEntityKind)
    assert.typeOf(entity.key, 'string')
    assert.isNotEmpty(entity.key)
    assert.instanceOf(entity.info, Thing)
    assert.equal(entity.info.name, 'new_entity')
    assert.deepEqual(entity.tags, [])
    assert.deepEqual(entity.semantics, [])
    assert.deepEqual(entity.fields, [])
    assert.isUndefined(entity.deprecated)
  })

  test('creates a new DomainEntity with provided values', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, {
      key: 'test-entity',
      info: { name: 'Test Entity', description: 'A test entity' },
      tags: ['tag1', 'tag2'],
      semantics: [{ id: SemanticType.User }],
      fields: [{ key: 'test-property', type: 'property' }],
      deprecated: true,
    })
    assert.equal(entity.kind, DomainEntityKind)
    assert.equal(entity.key, 'test-entity')
    assert.instanceOf(entity.info, Thing)
    assert.equal(entity.info.name, 'Test Entity')
    assert.equal(entity.info.description, 'A test entity')
    assert.deepEqual(entity.tags, ['tag1', 'tag2'])
    assert.deepEqual(entity.semantics, [{ id: SemanticType.User }])
    assert.deepEqual(entity.fields, [{ key: 'test-property', type: 'property' }])
    assert.isTrue(entity.deprecated)
  })

  test('creates a new DomainEntity with partial info', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, {
      info: { name: 'Test Entity' },
    })
    assert.equal(entity.kind, DomainEntityKind)
    assert.typeOf(entity.key, 'string')
    assert.isNotEmpty(entity.key)
    assert.instanceOf(entity.info, Thing)
    assert.equal(entity.info.name, 'Test Entity')
  })

  test('creates a new DomainEntity with empty info', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, {
      info: {},
    })
    assert.equal(entity.kind, DomainEntityKind)
    assert.typeOf(entity.key, 'string')
    assert.isNotEmpty(entity.key)
    assert.instanceOf(entity.info, Thing)
    assert.equal(entity.info.name, 'new_entity')
  })

  test('creates a new DomainEntity with tags', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, {
      tags: ['tag1', 'tag2'],
    })
    assert.equal(entity.kind, DomainEntityKind)
    assert.typeOf(entity.key, 'string')
    assert.isNotEmpty(entity.key)
    assert.instanceOf(entity.info, Thing)
    assert.equal(entity.info.name, 'new_entity')
    assert.deepEqual(entity.tags, ['tag1', 'tag2'])
  })

  test('creates a new DomainEntity with semantics', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, {
      semantics: [{ id: SemanticType.User }],
    })
    assert.equal(entity.kind, DomainEntityKind)
    assert.typeOf(entity.key, 'string')
    assert.isNotEmpty(entity.key)
    assert.instanceOf(entity.info, Thing)
    assert.equal(entity.info.name, 'new_entity')
    assert.deepEqual(entity.semantics, [{ id: SemanticType.User }])
  })

  test('creates a new DomainEntity with fields', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, {
      fields: [{ key: 'test-property', type: 'property' }],
    })
    assert.equal(entity.kind, DomainEntityKind)
    assert.typeOf(entity.key, 'string')
    assert.isNotEmpty(entity.key)
    assert.instanceOf(entity.info, Thing)
    assert.equal(entity.info.name, 'new_entity')
    assert.deepEqual(entity.fields, [{ key: 'test-property', type: 'property' }])
  })

  test('creates a new DomainEntity with deprecated set to true', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, {
      deprecated: true,
    })
    assert.equal(entity.kind, DomainEntityKind)
    assert.typeOf(entity.key, 'string')
    assert.isNotEmpty(entity.key)
    assert.instanceOf(entity.info, Thing)
    assert.equal(entity.info.name, 'new_entity')
    assert.isTrue(entity.deprecated)
  })

  test('creates a new DomainEntity with deprecated set to false', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, {
      deprecated: false,
    })
    assert.equal(entity.kind, DomainEntityKind)
    assert.typeOf(entity.key, 'string')
    assert.isNotEmpty(entity.key)
    assert.instanceOf(entity.info, Thing)
    assert.equal(entity.info.name, 'new_entity')
    assert.isFalse(entity.deprecated)
  })

  test('creates a new DomainEntity with a custom key', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, { key: 'custom-key' })
    assert.equal(entity.key, 'custom-key')
  })

  test('creates a new DomainEntity with custom info', ({ assert }) => {
    const dataDomain = new DataDomain()
    const customInfo = { name: 'Custom Name', description: 'Custom Description' }
    const entity = new DomainEntity(dataDomain, { info: customInfo })
    assert.deepInclude(entity.info, customInfo)
  })

  test('creates a new DomainEntity with custom tags', ({ assert }) => {
    const dataDomain = new DataDomain()
    const customTags = ['custom-tag1', 'custom-tag2']
    const entity = new DomainEntity(dataDomain, { tags: customTags })
    assert.deepEqual(entity.tags, customTags)
  })

  test('creates a new DomainEntity with custom semantics', ({ assert }) => {
    const dataDomain = new DataDomain()
    const customSemantics = [{ id: SemanticType.User }]
    const entity = new DomainEntity(dataDomain, { semantics: customSemantics })
    assert.deepEqual(entity.semantics, customSemantics)
  })

  test('creates a new DomainEntity with custom fields', ({ assert }) => {
    const dataDomain = new DataDomain()
    const customFields: EntityOrderedItem[] = [{ key: 'custom-property', type: 'property' }]
    const entity = new DomainEntity(dataDomain, { fields: customFields })
    assert.deepEqual(entity.fields, customFields)
  })

  test('creates a new DomainEntity with custom deprecated value', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entityTrue = new DomainEntity(dataDomain, { deprecated: true })
    assert.isTrue(entityTrue.deprecated)

    const entityFalse = new DomainEntity(dataDomain, { deprecated: false })
    assert.isFalse(entityFalse.deprecated)
  })

  test('sets deprecated to undefined when not provided', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, {})
    assert.isUndefined(entity.deprecated)
  })

  test('sets fields to empty array when not provided', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, {})
    assert.deepEqual(entity.fields, [])
  })

  test('sets fields to empty array when fields is undefined', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, { fields: undefined })
    assert.deepEqual(entity.fields, [])
  })
})

test.group('DomainEntity.toJSON()', () => {
  test('returns a valid schema with default values', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain)
    const json = entity.toJSON()
    assert.equal(json.kind, DomainEntityKind)
    assert.equal(json.key, entity.key)
    assert.deepInclude(json.info, { name: 'new_entity' })
    assert.isUndefined(json.tags)
    assert.isUndefined(json.semantics)
    assert.isUndefined(json.fields)
    assert.isUndefined(json.deprecated)
  })

  test('returns a valid schema with provided values', ({ assert }) => {
    const dataDomain = new DataDomain()
    const entity = new DomainEntity(dataDomain, {
      key: 'test-entity',
      info: { name: 'Test Entity', description: 'A test entity' },
      tags: ['tag1', 'tag2'],
      semantics: [{ id: SemanticType.User }],
      fields: [{ key: 'test-property', type: 'property' }],
      deprecated: true,
    })
    const json = entity.toJSON()
    assert.equal(json.kind, DomainEntityKind)
    assert.equal(json.key, 'test-entity')
    assert.deepInclude(json.info, { name: 'Test Entity', description: 'A test entity' })
    assert.deepEqual(json.tags, ['tag1', 'tag2'])
    assert.deepEqual(json.semantics, [{ id: SemanticType.User }])
    assert.deepEqual(json.fields, [{ key: 'test-property', type: 'property' }])
    assert.isTrue(json.deprecated)
  })

  test('includes child properties in the schema', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity({ key: 'test-entity' })
    const property = entity.addProperty({ type: 'string' })
    const json = entity.toJSON()
    assert.isArray(json.fields)
    assert.lengthOf(json.fields!, 1)
    assert.deepEqual(json.fields, [{ key: property.key, type: 'property' }])
  })

  test('includes child associations in the schema', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity({ key: 'test-entity' })
    const association = entity.addAssociation()
    const json = entity.toJSON()
    assert.isArray(json.fields)
    assert.lengthOf(json.fields!, 1)
    assert.deepEqual(json.fields, [{ key: association.key, type: 'association' }])
  })

  test('includes deprecated flag when true', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity({ key: 'test-entity', deprecated: true })
    const json = entity.toJSON()
    assert.isTrue(json.deprecated)
  })

  test('includes deprecated flag when false', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity({ key: 'test-entity', deprecated: false })
    const json = entity.toJSON()
    assert.isFalse(json.deprecated)
  })

  test('includes multiple fields in the correct order', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()
    const property1 = entity.addProperty({ type: 'string' })
    const association1 = entity.addAssociation()
    const property2 = entity.addProperty({ type: 'string' })
    const association2 = entity.addAssociation()
    const json = entity.toJSON()
    assert.isArray(json.fields)
    assert.lengthOf(json.fields!, 4)
    assert.deepEqual(json.fields, [
      { key: property1.key, type: 'property' },
      { key: association1.key, type: 'association' },
      { key: property2.key, type: 'property' },
      { key: association2.key, type: 'association' },
    ])
  })

  test('serializes the "info" property', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity({
      key: 'test-entity',
      info: { name: 'Test Name', description: 'Test Description' },
    })
    const json = entity.toJSON()
    assert.deepInclude(json.info, { name: 'Test Name', description: 'Test Description' })
  })

  test('serializes the "tags" property', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity({
      key: 'test-entity',
      tags: ['tag1', 'tag2'],
    })
    const json = entity.toJSON()
    assert.deepEqual(json.tags, ['tag1', 'tag2'])
  })

  test('serializes the "semantics" property', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity({
      key: 'test-entity',
      semantics: [{ id: SemanticType.User }],
    })
    const json = entity.toJSON()
    assert.deepEqual(json.semantics, [{ id: SemanticType.User }])
  })
})

test.group('DomainEntity.getParentInstance()', () => {
  test('returns the parent model when the entity is a child', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()
    const parent = entity.getParentInstance()
    assert.deepEqual(parent, model)
  })

  test('returns undefined when the entity has no parent', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()
    dataDomain.graph.removeParent(entity.key)
    const parent = entity.getParentInstance()
    assert.isUndefined(parent)
  })

  test('returns the correct parent when there are multiple levels of nesting', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()
    entity.addProperty()
    const parent = entity.getParentInstance()
    assert.deepEqual(parent, model)
  })

  test('returns the correct parent when the entity is attached to a different model', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model1 = dataDomain.addModel({ key: 'model1' })
    const model2 = dataDomain.addModel({ key: 'model2' })
    const entity = model1.addEntity({ key: 'entity1' })
    model2.attachEntity(entity.key)
    const parent = entity.getParentInstance()
    assert.deepEqual(parent, model2)
  })
})

test.group('DomainEntity.breadcrumbs()', () => {
  test('creates breadcrumbs from entity to data domain', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity({ info: { name: 'Test Entity' } })
    const breadcrumbs = entity.breadcrumbs()
    assert.lengthOf(breadcrumbs, 3)
    assert.deepEqual(breadcrumbs[0], {
      key: dataDomain.key,
      name: 'Unnamed domain',
      kind: DataDomainKind,
    })
    assert.deepEqual(breadcrumbs[1], {
      key: model.key,
      name: 'New model',
      kind: DomainModelKind,
    })
    assert.deepEqual(breadcrumbs[2], {
      key: entity.key,
      name: 'Test Entity',
      kind: DomainEntityKind,
    })
  })

  test('creates breadcrumbs from entity to data domain with custom names', ({ assert }) => {
    const dataDomain = new DataDomain()
    dataDomain.info.name = 'Custom Data Domain'
    const model = dataDomain.addModel({ info: { name: 'Test Model' } })
    const entity = model.addEntity({ info: { name: 'Test Entity' } })
    const breadcrumbs = entity.breadcrumbs()
    assert.lengthOf(breadcrumbs, 3)
    assert.deepEqual(breadcrumbs[0], {
      key: dataDomain.key,
      name: 'Custom Data Domain',
      kind: DataDomainKind,
    })
    assert.deepEqual(breadcrumbs[1], {
      key: model.key,
      name: 'Test Model',
      kind: DomainModelKind,
    })
    assert.deepEqual(breadcrumbs[2], {
      key: entity.key,
      name: 'Test Entity',
      kind: DomainEntityKind,
    })
  })

  test('creates breadcrumbs from entity to namespace to data domain', ({ assert }) => {
    const dataDomain = new DataDomain()
    const namespace = dataDomain.addNamespace({ info: { name: 'Test Namespace' } })
    const model = namespace.addModel({ info: { name: 'Test Model' } })
    const entity = model.addEntity({ info: { name: 'Test Entity' } })
    const breadcrumbs = entity.breadcrumbs()
    assert.lengthOf(breadcrumbs, 4)
    assert.deepEqual(breadcrumbs[0], {
      key: dataDomain.key,
      name: 'Unnamed domain',
      kind: DataDomainKind,
    })
    assert.deepEqual(breadcrumbs[1], {
      key: namespace.key,
      name: 'Test Namespace',
      kind: DomainNamespaceKind,
    })
    assert.deepEqual(breadcrumbs[2], {
      key: model.key,
      name: 'Test Model',
      kind: DomainModelKind,
    })
    assert.deepEqual(breadcrumbs[3], {
      key: entity.key,
      name: 'Test Entity',
      kind: DomainEntityKind,
    })
  })

  test('creates breadcrumbs from entity to nested namespaces to data domain', ({ assert }) => {
    const dataDomain = new DataDomain()
    const namespace1 = dataDomain.addNamespace({ info: { name: 'Test Namespace 1' } })
    const namespace2 = namespace1.addNamespace({ info: { name: 'Test Namespace 2' } })
    const model = namespace2.addModel({ info: { name: 'Test Model' } })
    const entity = model.addEntity({ info: { name: 'Test Entity' } })
    const breadcrumbs = entity.breadcrumbs()
    assert.lengthOf(breadcrumbs, 5)
    assert.deepEqual(breadcrumbs[0], {
      key: dataDomain.key,
      name: 'Unnamed domain',
      kind: DataDomainKind,
    })
    assert.deepEqual(breadcrumbs[1], {
      key: namespace1.key,
      name: 'Test Namespace 1',
      kind: DomainNamespaceKind,
    })
    assert.deepEqual(breadcrumbs[2], {
      key: namespace2.key,
      name: 'Test Namespace 2',
      kind: DomainNamespaceKind,
    })
    assert.deepEqual(breadcrumbs[3], {
      key: model.key,
      name: 'Test Model',
      kind: DomainModelKind,
    })
    assert.deepEqual(breadcrumbs[4], {
      key: entity.key,
      name: 'Test Entity',
      kind: DomainEntityKind,
    })
  })

  test('creates breadcrumbs with unnamed data domain, namespaces, and entity', ({ assert }) => {
    const dataDomain = new DataDomain()
    dataDomain.info.name = undefined
    const namespace1 = dataDomain.addNamespace()
    namespace1.info.name = undefined
    const namespace2 = namespace1.addNamespace()
    namespace2.info.name = undefined
    const model = namespace2.addModel()
    model.info.name = undefined
    const entity = model.addEntity()
    entity.info.name = undefined
    const breadcrumbs = entity.breadcrumbs()
    assert.lengthOf(breadcrumbs, 5)
    assert.deepEqual(breadcrumbs[0], {
      key: dataDomain.key,
      name: 'Unnamed data domain',
      kind: DataDomainKind,
    })
    assert.deepEqual(breadcrumbs[1], {
      key: namespace1.key,
      name: 'Unnamed namespace',
      kind: DomainNamespaceKind,
    })
    assert.deepEqual(breadcrumbs[2], {
      key: namespace2.key,
      name: 'Unnamed namespace',
      kind: DomainNamespaceKind,
    })
    assert.deepEqual(breadcrumbs[3], {
      key: model.key,
      name: 'Unnamed model',
      kind: DomainModelKind,
    })
    assert.deepEqual(breadcrumbs[4], {
      key: entity.key,
      name: 'Unnamed entity',
      kind: DomainEntityKind,
    })
  })
})

test.group('DomainEntity.isChildOf()', () => {
  test('returns false when called on self', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()
    assert.isFalse(entity.isChildOf(entity.key))
  })

  test('returns true when called on a direct parent (DomainModel)', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()
    assert.isTrue(entity.isChildOf(model.key))
  })

  test('returns true when called on a grandparent (DomainNamespace)', ({ assert }) => {
    const dataDomain = new DataDomain()
    const namespace = dataDomain.addNamespace()
    const model = namespace.addModel()
    const entity = model.addEntity()
    assert.isTrue(entity.isChildOf(namespace.key))
  })

  test('returns true when called on a great-grandparent (DataDomain)', ({ assert }) => {
    const dataDomain = new DataDomain()
    const namespace = dataDomain.addNamespace()
    const model = namespace.addModel()
    const entity = model.addEntity()
    assert.isTrue(entity.isChildOf(dataDomain.key))
  })

  test('returns false when called on a sibling entity', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity1 = model.addEntity()
    const entity2 = model.addEntity()
    assert.isFalse(entity1.isChildOf(entity2.key))
  })

  test('returns false when called on a child property', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()
    const property = entity.addProperty()
    assert.isFalse(entity.isChildOf(property.key))
  })

  test('returns false when called on a non-existent key', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()
    assert.isFalse(entity.isChildOf('non-existent-key'))
  })

  test('returns false when the entity has no parent', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()
    dataDomain.graph.removeParent(entity.key)
    assert.isFalse(entity.isChildOf(model.key))
  })

  test('returns true when there are multiple levels of nesting', ({ assert }) => {
    const dataDomain = new DataDomain()
    const namespace = dataDomain.addNamespace()
    const model = namespace.addModel()
    const entity = model.addEntity()
    assert.isTrue(entity.isChildOf(dataDomain.key))
  })
})

test.group('DomainEntity.generateUniqueName()', () => {
  test('generates unique name when no fields exist', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()

    const uniqueName = entity.generateUniqueName('test')
    assert.equal(uniqueName, 'test_copy')
  })

  test('generates unique name when base name does not conflict', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()

    // Add a property with a different name
    entity.addProperty({ info: { name: 'existing_field' } })

    const uniqueName = entity.generateUniqueName('test')
    assert.equal(uniqueName, 'test_copy')
  })

  test('generates unique name when base_copy conflicts with existing property', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()

    // Add a property that conflicts with the first generated name
    entity.addProperty({ info: { name: 'test_copy' } })

    const uniqueName = entity.generateUniqueName('test')
    assert.equal(uniqueName, 'test_copy_2')
  })

  test('generates unique name when multiple conflicts exist with properties', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()

    // Add properties that conflict with multiple generated names
    entity.addProperty({ info: { name: 'test_copy' } })
    entity.addProperty({ info: { name: 'test_copy_2' } })
    entity.addProperty({ info: { name: 'test_copy_3' } })

    const uniqueName = entity.generateUniqueName('test')
    assert.equal(uniqueName, 'test_copy_4')
  })

  test('generates unique name when conflicts exist with associations', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()
    const targetEntity = model.addEntity()

    // Add an association that conflicts with the first generated name
    const association = entity.addAssociation({ key: targetEntity.key })
    association.info.name = 'test_copy'

    const uniqueName = entity.generateUniqueName('test')
    assert.equal(uniqueName, 'test_copy_2')
  })

  test('generates unique name when conflicts exist with both properties and associations', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()
    const targetEntity = model.addEntity()

    // Add property and association with conflicting names
    entity.addProperty({ info: { name: 'test_copy' } })
    const association = entity.addAssociation({ key: targetEntity.key })
    association.info.name = 'test_copy_2'

    const uniqueName = entity.generateUniqueName('test')
    assert.equal(uniqueName, 'test_copy_3')
  })

  test('handles fields with undefined names', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()
    const targetEntity = model.addEntity()

    // Add property without a name (undefined name)
    entity.addProperty({ info: {} })
    // Add association without a name
    entity.addAssociation({ key: targetEntity.key })

    const uniqueName = entity.generateUniqueName('test')
    assert.equal(uniqueName, 'test_copy')
  })

  test('generates incrementing counter correctly', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()

    // Add many conflicting properties to test counter increment
    for (let i = 0; i < 10; i++) {
      const name = i === 0 ? 'test_copy' : `test_copy_${i + 1}`
      entity.addProperty({ info: { name } })
    }

    const uniqueName = entity.generateUniqueName('test')
    assert.equal(uniqueName, 'test_copy_11')
  })

  test('works with different base names', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()

    entity.addProperty({ info: { name: 'user_copy' } })
    entity.addProperty({ info: { name: 'product_copy' } })

    const userUnique = entity.generateUniqueName('user')
    const productUnique = entity.generateUniqueName('product')
    const orderUnique = entity.generateUniqueName('order')

    assert.equal(userUnique, 'user_copy_2')
    assert.equal(productUnique, 'product_copy_2')
    assert.equal(orderUnique, 'order_copy')
  })

  test('handles empty base name', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()

    const uniqueName = entity.generateUniqueName('')
    assert.equal(uniqueName, '_copy')
  })

  test('case sensitive name comparison', ({ assert }) => {
    const dataDomain = new DataDomain()
    const model = dataDomain.addModel()
    const entity = model.addEntity()

    // Add property with uppercase name
    entity.addProperty({ info: { name: 'TEST_COPY' } })

    // Should not conflict because comparison is case-sensitive
    const uniqueName = entity.generateUniqueName('test')
    assert.equal(uniqueName, 'test_copy')
  })
})
