import { test } from '@japa/runner'
import { ListAction } from '../../../../src/modeling/actions/ListAction.js'
import { PaginationStrategy } from '../../../../src/modeling/types.js'

test.group('ListAction', () => {
  test('initializes with default values', ({ assert }) => {
    const action = new ListAction()
    assert.equal(action.kind, 'list')
    assert.deepEqual(action.pagination, { kind: 'offset' })
    assert.deepEqual(action.filterableFields, [])
    assert.deepEqual(action.sortableFields, [])
    assert.isEmpty(action.accessRule) // Inherited from Action
  }).tags(['@modeling', '@action', '@list-action'])

  test('initializes with provided values', ({ assert }) => {
    const pagination: PaginationStrategy = { kind: 'cursor' }
    const filterableFields = ['name', 'status']
    const sortableFields = ['createdAt']

    const action = new ListAction({
      pagination,
      filterableFields,
      sortableFields,
    })

    assert.deepEqual(action.pagination, pagination)
    assert.deepEqual(action.filterableFields, filterableFields)
    assert.deepEqual(action.sortableFields, sortableFields)
  }).tags(['@modeling', '@action', '@list-action'])

  test('constructor copies arrays and objects (immutability)', ({ assert }) => {
    const pagination: PaginationStrategy = { kind: 'offset' }
    const filterableFields = ['name']
    const sortableFields = ['name']

    const action = new ListAction({
      pagination,
      filterableFields,
      sortableFields,
    })

    // Modify original sources
    pagination.kind = 'cursor'
    filterableFields.push('age')
    sortableFields.push('age')

    assert.deepEqual(action.pagination, { kind: 'offset' })
    assert.deepEqual(action.filterableFields, ['name'])
    assert.deepEqual(action.sortableFields, ['name'])
  }).tags(['@modeling', '@action', '@list-action', '@immutability'])

  test('toJSON returns safe copy', ({ assert }) => {
    const action = new ListAction({
      pagination: { kind: 'offset' },
      filterableFields: ['name'],
      sortableFields: ['name'],
    })

    const json = action.toJSON()

    // Modify JSON
    json.pagination.kind = 'cursor'
    json.filterableFields.push('new')
    json.sortableFields.push('new')

    assert.deepEqual(action.pagination, { kind: 'offset' })
    assert.deepEqual(action.filterableFields, ['name'])
    assert.deepEqual(action.sortableFields, ['name'])
  }).tags(['@modeling', '@action', '@list-action', '@immutability'])

  test('notifies change when pagination changes', async ({ assert }) => {
    const action = new ListAction()
    let notified = false
    action.addEventListener('change', () => {
      notified = true
    })

    action.pagination = { kind: 'cursor' }
    await Promise.resolve()
    assert.isTrue(notified)
  }).tags(['@modeling', '@action', '@list-action', '@observed'])

  test('notifies change when filterableFields changes', async ({ assert }) => {
    const action = new ListAction()
    let notified = false
    action.addEventListener('change', () => {
      notified = true
    })

    action.filterableFields = ['name']
    await Promise.resolve()
    assert.isTrue(notified)
  }).tags(['@modeling', '@action', '@list-action', '@observed'])

  test('notifies change when sortableFields changes', async ({ assert }) => {
    const action = new ListAction()
    let notified = false
    action.addEventListener('change', () => {
      notified = true
    })

    action.sortableFields = ['name']
    await Promise.resolve()
    assert.isTrue(notified)
  }).tags(['@modeling', '@action', '@list-action', '@observed'])
})
