import { test } from '@japa/runner'
import { ApiModel, DataDomain } from '../../../src/index.js'

test.group('ApiModel.removeEntity()', () => {
  test('removes an existing entity', ({ assert }) => {
    const domain = new DataDomain()
    domain.info.version = '1.0.0'
    const dm = domain.addModel()
    const e1 = dm.addEntity()
    const model = new ApiModel()
    model.attachDataDomain(domain)
    model.exposeEntity({ key: e1.key })
    assert.lengthOf(model.exposes, 1)

    model.removeEntity({ key: e1.key })
    assert.lengthOf(model.exposes, 0)
  }).tags(['@modeling', '@api'])

  test('removes an entity and its nested children', ({ assert }) => {
    const domain = new DataDomain()
    domain.info.version = '1.0.0'
    const dm = domain.addModel()
    const eA = dm.addEntity({ info: { name: 'A' } })
    const eB = dm.addEntity({ info: { name: 'B' } })
    // A -> B
    eA.addAssociation({ key: eB.key }, { info: { name: 'toB' } })
    const model = new ApiModel()
    model.attachDataDomain(domain)
    model.exposeEntity({ key: eA.key }, { followAssociations: true })
    // Ensure nested exposure for B was created
    const nestedB = model.exposes.find((e) => !e.isRoot && e.entity.key === eB.key)
    assert.isDefined(nestedB)
    assert.isAbove(model.exposes.length, 1)

    // Remove root entity A and expect children to be removed as well
    model.removeEntity({ key: eA.key })
    assert.lengthOf(model.exposes, 0)
  }).tags(['@modeling', '@api'])

  test('does nothing if entity does not exist', ({ assert }) => {
    const domain = new DataDomain()
    domain.info.version = '1.0.0'
    const dm = domain.addModel()
    const e1 = dm.addEntity()
    const model = new ApiModel()
    model.attachDataDomain(domain)
    model.exposeEntity({ key: e1.key })

    model.removeEntity({ key: 'non-existing-entity' })
    assert.lengthOf(model.exposes, 1, 'exposes count should remain unchanged')
  }).tags(['@modeling', '@api'])

  test('notifies change when an entity is removed', async ({ assert }) => {
    const domain = new DataDomain()
    domain.info.version = '1.0.0'
    const dm = domain.addModel()
    const e1 = dm.addEntity()
    const model = new ApiModel()
    model.attachDataDomain(domain)
    model.exposeEntity({ key: e1.key })

    let notified = false
    model.addEventListener('change', () => {
      notified = true
    })
    model.removeEntity({ key: e1.key })
    await Promise.resolve() // Allow microtask to run
    assert.isTrue(notified)
  }).tags(['@modeling', '@api'])

  test('does not notify change if entity to remove does not exist', async ({ assert }) => {
    const model = new ApiModel()
    let notified = false
    model.addEventListener('change', () => {
      notified = true
    })
    model.removeEntity({ key: 'no-notify-remove-entity' })
    await Promise.resolve() // Allow microtask to run
    assert.isFalse(notified)
  }).tags(['@modeling', '@api'])
})
