import { test } from '@japa/runner'
import type { JSONSchema7 } from 'json-schema'
import { DataDomain } from '../../../../src/modeling/DataDomain.js'
import {
  FilteringJsonSchemaImporter,
  SchemaFilteringUtils,
} from '../../../../src/modeling/importers/FilteringJsonSchemaImporter.js'
import {
  SchemaFilteringStrategy,
  FILTERING_STRATEGIES,
} from '../../../../src/modeling/importers/SchemaFilteringStrategy.js'
import type { InMemorySchema } from '../../../../src/modeling/importers/JsonSchemaImporter.js'

test.group('SchemaFilteringStrategy', () => {
  test('should identify empty object schemas', ({ assert }) => {
    const strategy = new SchemaFilteringStrategy({ excludeEmptyObjects: true })

    const emptySchema: JSONSchema7 = {
      type: 'object',
      title: 'EmptyObject',
      description: 'An empty object',
    }

    const nonEmptySchema: JSONSchema7 = {
      type: 'object',
      title: 'NonEmptyObject',
      properties: {
        name: { type: 'string' },
      },
    }

    assert.isTrue(strategy.shouldExcludeSchema(emptySchema))
    assert.isFalse(strategy.shouldExcludeSchema(nonEmptySchema))
  })

  test('should identify conceptual marker schemas', ({ assert }) => {
    const strategy = new SchemaFilteringStrategy({ excludeConceptualMarkers: true })

    // StatusEnumeration-like schema (empty object, should be excluded)
    const statusEnum: JSONSchema7 = {
      type: 'object',
      title: 'StatusEnumeration',
      description: 'Lists or enumerations dealing with status types.',
    }

    // ActionStatusType-like schema (allOf with reference only - represents inheritance, should NOT be excluded)
    const actionStatus: JSONSchema7 = {
      type: 'object',
      title: 'ActionStatusType',
      description: 'The status of an Action.',
      allOf: [{ $ref: 'schema:StatusEnumeration' }],
    }

    // Real schema with properties
    const person: JSONSchema7 = {
      type: 'object',
      title: 'Person',
      properties: {
        name: { type: 'string' },
      },
    }

    assert.isTrue(strategy.shouldExcludeSchema(statusEnum))
    assert.isFalse(strategy.shouldExcludeSchema(actionStatus)) // Changed: inheritance should not be excluded
    assert.isFalse(strategy.shouldExcludeSchema(person))
  })

  test('should preserve schema inheritance patterns', ({ assert }) => {
    const strategy = new SchemaFilteringStrategy({ excludeConceptualMarkers: true })

    // BlogPosting schema - extends SocialMediaPosting via allOf
    const blogPosting: JSONSchema7 = {
      $schema: 'https://json-schema.org/draft/2020-12/schema',
      $id: 'schema:BlogPosting',
      title: 'BlogPosting',
      description: 'A blog post.',
      type: 'object',
      allOf: [
        {
          description: 'A post to a social media platform, including blog posts, tweets, Facebook posts, etc.',
          $ref: 'schema:SocialMediaPosting',
        },
      ],
    }

    // SocialMediaPosting schema - has properties and extends Article
    const socialMediaPosting: JSONSchema7 = {
      $schema: 'https://json-schema.org/draft/2020-12/schema',
      $id: 'schema:SocialMediaPosting',
      title: 'SocialMediaPosting',
      description: 'A post to a social media platform, including blog posts, tweets, Facebook posts, etc.',
      type: 'object',
      allOf: [
        {
          description: 'An article, such as a news article or piece of investigative report.',
          $ref: 'schema:Article',
        },
      ],
      properties: {
        sharedContent: {
          description: 'A CreativeWork such as an image, video, or audio clip shared as part of this posting.',
          oneOf: [{ $ref: 'schema:CreativeWork' }, { type: 'array', items: { $ref: 'schema:CreativeWork' } }],
        },
      },
    }

    // Both schemas represent valid inheritance and should be included
    assert.isFalse(strategy.shouldExcludeSchema(blogPosting, 'schema:BlogPosting'))
    assert.isFalse(strategy.shouldExcludeSchema(socialMediaPosting, 'schema:SocialMediaPosting'))
  })

  test('should filter by patterns', ({ assert }) => {
    const strategy = new SchemaFilteringStrategy({
      excludePatterns: [/.*Enumeration$/, /.*Type$/],
    })

    assert.isTrue(strategy.shouldExcludeSchema({} as JSONSchema7, 'StatusEnumeration'))
    assert.isTrue(strategy.shouldExcludeSchema({} as JSONSchema7, 'BusinessEntityType'))
    assert.isFalse(strategy.shouldExcludeSchema({} as JSONSchema7, 'Person'))
  })

  test('should use custom exclusion filter', ({ assert }) => {
    const strategy = new SchemaFilteringStrategy({
      customExclusionFilter: (schema) => schema.title?.includes('Custom') ?? false,
    })

    const customSchema: JSONSchema7 = { title: 'CustomSchema' }
    const normalSchema: JSONSchema7 = { title: 'NormalSchema' }

    assert.isTrue(strategy.shouldExcludeSchema(customSchema))
    assert.isFalse(strategy.shouldExcludeSchema(normalSchema))
  })

  test('should handle schemas with additionalProperties', ({ assert }) => {
    const strategy = new SchemaFilteringStrategy({ excludeEmptyObjects: true })

    const schemaWithAdditional: JSONSchema7 = {
      type: 'object',
      title: 'FlexibleObject',
      additionalProperties: true,
    }

    const schemaWithAdditionalSchema: JSONSchema7 = {
      type: 'object',
      title: 'ConstrainedObject',
      additionalProperties: { type: 'string' },
    }

    // These should NOT be filtered because additionalProperties provides structure
    assert.isFalse(strategy.shouldExcludeSchema(schemaWithAdditional))
    assert.isFalse(strategy.shouldExcludeSchema(schemaWithAdditionalSchema))
  })

  test('should handle schemas with constraints but no properties', ({ assert }) => {
    const strategy = new SchemaFilteringStrategy({ excludeEmptyObjects: true })

    const constrainedSchema: JSONSchema7 = {
      type: 'object',
      title: 'ConstrainedObject',
      minProperties: 1,
      maxProperties: 5,
    }

    // Should NOT be filtered because it has structural constraints
    assert.isFalse(strategy.shouldExcludeSchema(constrainedSchema))
  })

  test('should provide meaningful exclusion reasons', ({ assert }) => {
    const strategy = new SchemaFilteringStrategy({
      excludeEmptyObjects: true,
      excludeConceptualMarkers: true,
      excludeSchemaIds: ['exclude:this'],
    })

    const emptySchema: JSONSchema7 = { type: 'object' }
    const markerSchema: JSONSchema7 = {
      type: 'object',
      title: 'Marker',
      description: 'Just a marker',
    }

    assert.include(strategy.getExclusionReason(emptySchema), 'empty object')
    // The markerSchema is actually identified as empty object, not conceptual marker
    assert.include(strategy.getExclusionReason(markerSchema), 'empty object')
    assert.include(strategy.getExclusionReason({} as JSONSchema7, 'exclude:this'), 'exclusion list')
  })
})

test.group('Predefined Filtering Strategies', () => {
  const testSchemas = [
    {
      id: 'schema:StatusEnumeration',
      schema: { type: 'object', title: 'StatusEnumeration' } as JSONSchema7,
    },
    {
      id: 'schema:BusinessEntityType',
      schema: { type: 'object', title: 'BusinessEntityType' } as JSONSchema7,
    },
    {
      id: 'schema:Person',
      schema: { type: 'object', title: 'Person', properties: { name: { type: 'string' } } } as JSONSchema7,
    },
  ]

  test('API_MODELING strategy should filter enumeration and type schemas', ({ assert }) => {
    const stats = SchemaFilteringUtils.getFilteringStats(testSchemas, FILTERING_STRATEGIES.API_MODELING)

    assert.equal(stats.total, 3)
    assert.equal(stats.filtered, 2) // StatusEnumeration and BusinessEntityType
    assert.equal(stats.remaining, 1) // Person
    assert.deepEqual(
      stats.filteredSchemas.map((f) => f.id),
      ['schema:StatusEnumeration', 'schema:BusinessEntityType']
    )
  })

  test('DATABASE_MODELING strategy should be very strict', ({ assert }) => {
    const stats = SchemaFilteringUtils.getFilteringStats(testSchemas, FILTERING_STRATEGIES.DATABASE_MODELING)

    assert.equal(stats.filtered, 2) // Should filter empty objects
    assert.equal(stats.remaining, 1) // Only Person with properties
  })

  test('CONSERVATIVE strategy should only filter obviously empty schemas', ({ assert }) => {
    const stats = SchemaFilteringUtils.getFilteringStats(testSchemas, FILTERING_STRATEGIES.CONSERVATIVE)

    assert.equal(stats.filtered, 2) // Only truly empty objects
    assert.equal(stats.remaining, 1)
  })
})

test.group('Schema References and Dependencies', () => {
  const createTestSchemas = (): InMemorySchema[] => [
    // Empty marker schema
    {
      path: 'schema:StatusEnumeration',
      contents: {
        $id: 'schema:StatusEnumeration',
        type: 'object',
        title: 'StatusEnumeration',
        description: 'Lists or enumerations dealing with status types.',
      } as JSONSchema7,
    },
    // Schema that references the empty marker
    {
      path: 'schema:ActionStatusType',
      contents: {
        $id: 'schema:ActionStatusType',
        type: 'object',
        title: 'ActionStatusType',
        allOf: [{ $ref: 'schema:StatusEnumeration' }],
      } as JSONSchema7,
    },
    // Schema with property referencing filtered schema
    {
      path: 'schema:Task',
      contents: {
        $id: 'schema:Task',
        type: 'object',
        title: 'Task',
        properties: {
          name: { type: 'string' },
          status: { $ref: 'schema:ActionStatusType' },
        },
        required: ['name'],
      } as JSONSchema7,
    },
    // Schema inheriting from filtered schema
    {
      path: 'schema:UrgentTask',
      contents: {
        $id: 'schema:UrgentTask',
        type: 'object',
        title: 'UrgentTask',
        allOf: [
          { $ref: 'schema:Task' },
          {
            properties: {
              priority: { type: 'string', enum: ['high', 'urgent'] },
            },
          },
        ],
      } as JSONSchema7,
    },
    // Concrete schema that should be kept
    {
      path: 'schema:Person',
      contents: {
        $id: 'schema:Person',
        type: 'object',
        title: 'Person',
        properties: {
          name: { type: 'string' },
          email: { type: 'string' },
        },
        required: ['name'],
      } as JSONSchema7,
    },
  ]

  test('should handle schemas with filtered dependencies - no filtering', async ({ assert }) => {
    const domain = new DataDomain({ key: 'test-domain', info: { name: 'Test Domain' } })
    const schemas = createTestSchemas()
    const importer = new FilteringJsonSchemaImporter(domain)

    const result = await importer.import(schemas, 'TestModel')
    const entities = Array.from(result.model.listEntities())

    // Without filtering, all schemas should create entities
    assert.isAtLeast(entities.length, 5)

    const entityNames = entities.map((e) => e.info.name)
    assert.include(entityNames, 'action_status_type')
    assert.include(entityNames, 'person')
    assert.include(entityNames, 'status_enumeration')
    assert.include(entityNames, 'task')
    assert.include(entityNames, 'urgent_task')
  })

  test('should handle schemas with filtered dependencies - API modeling', async ({ assert }) => {
    const domain = new DataDomain({ key: 'test-domain', info: { name: 'Test Domain' } })
    const schemas = createTestSchemas()
    const importer = FilteringJsonSchemaImporter.forApiModeling(domain)

    const result = await importer.import(schemas, 'ApiModel')
    const entities = Array.from(result.model.listEntities())

    // Should filter StatusEnumeration and ActionStatusType (ends with Type)
    // Task and UrgentTask should remain (they have concrete properties)
    // Person should remain
    assert.isAtMost(entities.length, 3)

    const entityNames = entities.map((e) => e.info.name)
    assert.include(entityNames, 'person')
    assert.include(entityNames, 'task')
    // Note: UrgentTask uses allOf so it may be created as a mixin entity
    assert.isAtLeast(entityNames.length, 2) // At least person and task

    // Check filtering messages
    const filterMessages = result.messages.filter((m) => m.message.includes('filtered'))
    assert.isAtLeast(filterMessages.length, 1)
  })

  test('should handle schemas with filtered dependencies - Database modeling', async ({ assert }) => {
    const domain = new DataDomain({ key: 'test-domain', info: { name: 'Test Domain' } })
    const schemas = createTestSchemas()
    const importer = FilteringJsonSchemaImporter.forDatabaseModeling(domain)

    const result = await importer.import(schemas, 'DatabaseModel')
    const entities = Array.from(result.model.listEntities())

    // Database modeling should be very strict - only keep schemas with concrete properties
    const entityNames = entities.map((e) => e.info.name)
    assert.include(entityNames, 'person') // Has concrete properties
    assert.include(entityNames, 'task') // Has concrete properties
    // Note: UrgentTask uses allOf so it may be created as a mixin entity
    assert.isAtLeast(entityNames.length, 2) // At least person and task

    // Should filter empty marker schemas
    assert.notInclude(entityNames, 'status_enumeration')

    // Check that we have filtering messages
    const filterMessages = result.messages.filter((m) => m.message.includes('filtered'))
    assert.isAtLeast(filterMessages.length, 1)
  })

  test('should clean up orphaned associations after filtering', async ({ assert }) => {
    const domain = new DataDomain({ key: 'test-domain', info: { name: 'Test Domain' } })
    const schemas: InMemorySchema[] = [
      {
        path: 'schema:EmptyMarker',
        contents: {
          $id: 'schema:EmptyMarker',
          type: 'object',
          title: 'EmptyMarker',
        } as JSONSchema7,
      },
      {
        path: 'schema:User',
        contents: {
          $id: 'schema:User',
          type: 'object',
          title: 'User',
          properties: {
            name: { type: 'string' },
            marker: { $ref: 'schema:EmptyMarker' },
          },
        } as JSONSchema7,
      },
    ]

    const importer = FilteringJsonSchemaImporter.forDatabaseModeling(domain)
    const result = await importer.import(schemas, 'CleanupModel')

    // EmptyMarker should be filtered out
    const entities = Array.from(result.model.listEntities())
    const entityNames = entities.map((e) => e.info.name)
    assert.include(entityNames, 'user')
    assert.notInclude(entityNames, 'empty_marker')

    // Check for cleanup messages
    const cleanupMessages = result.messages.filter(
      (m) => m.message.includes('association') || m.message.includes('orphaned')
    )
    assert.isAtLeast(cleanupMessages.length, 0) // May or may not have associations to clean up
  })
})

test.group('Complex Inheritance Scenarios', () => {
  test('should handle inheritance chains with filtered base classes', async ({ assert }) => {
    const domain = new DataDomain({ key: 'test-domain', info: { name: 'Test Domain' } })
    const schemas: InMemorySchema[] = [
      {
        path: 'schema:BaseType',
        contents: {
          $id: 'schema:BaseType',
          type: 'object',
          title: 'BaseType',
          description: 'A base conceptual type',
        } as JSONSchema7,
      },
      {
        path: 'schema:MiddleType',
        contents: {
          $id: 'schema:MiddleType',
          type: 'object',
          title: 'MiddleType',
          allOf: [{ $ref: 'schema:BaseType' }],
        } as JSONSchema7,
      },
      {
        path: 'schema:ConcreteEntity',
        contents: {
          $id: 'schema:ConcreteEntity',
          type: 'object',
          title: 'ConcreteEntity',
          allOf: [
            { $ref: 'schema:MiddleType' },
            {
              properties: {
                id: { type: 'string' },
                name: { type: 'string' },
              },
              required: ['id'],
            },
          ],
        } as JSONSchema7,
      },
    ]

    const importer = FilteringJsonSchemaImporter.forDatabaseModeling(domain)
    const result = await importer.import(schemas, 'InheritanceModel')

    const entities = Array.from(result.model.listEntities())
    const entityNames = entities.map((e) => e.info.name)

    // Check what entities were actually created
    assert.isAtLeast(entities.length, 1)

    // Base types should be filtered
    assert.notInclude(entityNames, 'base_type')

    // Check that some entity with ConcreteEntity properties was created
    const concreteEntity = entities.find((e) => e.info.name?.includes('concrete_entity'))
    assert.isNotNull(concreteEntity)

    const properties = Array.from(concreteEntity!.listProperties())
    assert.isAtLeast(properties.length, 1) // Should have some properties
  })

  test('should handle circular references with filtered schemas', async ({ assert }) => {
    const domain = new DataDomain({ key: 'test-domain', info: { name: 'Test Domain' } })
    const schemas: InMemorySchema[] = [
      {
        path: 'schema:TypeA',
        contents: {
          $id: 'schema:TypeA',
          type: 'object',
          title: 'TypeA',
          properties: {
            refToB: { $ref: 'schema:TypeB' },
          },
        } as JSONSchema7,
      },
      {
        path: 'schema:TypeB',
        contents: {
          $id: 'schema:TypeB',
          type: 'object',
          title: 'TypeB',
          description: 'Empty marker type',
        } as JSONSchema7,
      },
    ]

    const importer = FilteringJsonSchemaImporter.forApiModeling(domain)
    const result = await importer.import(schemas, 'CircularModel')

    // Should handle this gracefully without infinite loops
    assert.isArray(result.messages)

    const entities = Array.from(result.model.listEntities())
    assert.isAtLeast(entities.length, 0) // Should not crash
  })
})

test.group('Property and Parent Reference Filtering', () => {
  test('should handle schemas where filtered types are used as property types', async ({ assert }) => {
    const domain = new DataDomain({ key: 'test-domain', info: { name: 'Test Domain' } })
    const schemas: InMemorySchema[] = [
      // Empty enumeration that should be filtered
      {
        path: 'schema:StatusEnumeration',
        contents: {
          $id: 'schema:StatusEnumeration',
          type: 'object',
          title: 'StatusEnumeration',
          description: 'Status enumeration values',
        } as JSONSchema7,
      },
      // Entity that has a property referencing the filtered schema
      {
        path: 'schema:Order',
        contents: {
          $id: 'schema:Order',
          type: 'object',
          title: 'Order',
          properties: {
            id: { type: 'string' },
            amount: { type: 'number' },
            status: { $ref: 'schema:StatusEnumeration' }, // References filtered schema
          },
          required: ['id', 'amount'],
        } as JSONSchema7,
      },
      // Entity with array property referencing filtered schema
      {
        path: 'schema:StatusHistory',
        contents: {
          $id: 'schema:StatusHistory',
          type: 'object',
          title: 'StatusHistory',
          properties: {
            orderId: { type: 'string' },
            statusChanges: {
              type: 'array',
              items: { $ref: 'schema:StatusEnumeration' }, // Array of filtered schema
            },
          },
          required: ['orderId'],
        } as JSONSchema7,
      },
    ]

    const importer = FilteringJsonSchemaImporter.forDatabaseModeling(domain)
    const result = await importer.import(schemas, 'PropertyRefModel')

    const entities = Array.from(result.model.listEntities())
    const entityNames = entities.map((e) => e.info.name)

    // StatusEnumeration should be filtered out
    assert.notInclude(entityNames, 'status_enumeration')

    // Order and StatusHistory should remain (they have concrete properties)
    assert.include(entityNames, 'order')
    assert.include(entityNames, 'status_history')

    // Check that the entities have the expected properties
    const orderEntity = entities.find((e) => e.info.name === 'order')
    assert.isNotNull(orderEntity)

    const orderProperties = Array.from(orderEntity!.listProperties())
    assert.isAtLeast(orderProperties.length, 2) // id and amount at minimum

    // Check for filtering messages about the StatusEnumeration
    const filterMessages = result.messages.filter(
      (m) => m.message.includes('filtered') && m.message.includes('status_enumeration')
    )
    assert.isAtLeast(filterMessages.length, 0) // May or may not have specific messages
  })

  test('should handle schemas where filtered types are used as parent classes', async ({ assert }) => {
    const domain = new DataDomain({ key: 'test-domain', info: { name: 'Test Domain' } })
    const schemas: InMemorySchema[] = [
      // Abstract base that should be filtered
      {
        path: 'schema:BaseEntity',
        contents: {
          $id: 'schema:BaseEntity',
          type: 'object',
          title: 'BaseEntity',
          description: 'Base entity without concrete properties',
        } as JSONSchema7,
      },
      // Another abstract type that extends the base
      {
        path: 'schema:TimestampedEntity',
        contents: {
          $id: 'schema:TimestampedEntity',
          type: 'object',
          title: 'TimestampedEntity',
          allOf: [
            { $ref: 'schema:BaseEntity' },
            {
              properties: {
                createdAt: { type: 'string', format: 'date-time' },
                updatedAt: { type: 'string', format: 'date-time' },
              },
            },
          ],
        } as JSONSchema7,
      },
      // Concrete entity that inherits from timestamped entity
      {
        path: 'schema:Product',
        contents: {
          $id: 'schema:Product',
          type: 'object',
          title: 'Product',
          allOf: [
            { $ref: 'schema:TimestampedEntity' },
            {
              properties: {
                id: { type: 'string' },
                name: { type: 'string' },
                price: { type: 'number' },
              },
              required: ['id', 'name', 'price'],
            },
          ],
        } as JSONSchema7,
      },
    ]

    const importer = FilteringJsonSchemaImporter.forDatabaseModeling(domain)
    const result = await importer.import(schemas, 'InheritanceModel')

    const entities = Array.from(result.model.listEntities())
    const entityNames = entities.map((e) => e.info.name)

    // BaseEntity should be filtered (no concrete properties)
    assert.notInclude(entityNames, 'base_entity')

    // Some entities should remain (they have properties)
    assert.isAtLeast(entities.length, 1)

    // Check that Product has all the expected properties
    const productEntity = entities.find((e) => e.info.name?.includes('product'))
    assert.isNotNull(productEntity)

    const productProperties = Array.from(productEntity!.listProperties())
    assert.isAtLeast(productProperties.length, 3) // At least id, name, price

    // Check for inheritance relationships (associations)
    const productAssociations = Array.from(productEntity!.listAssociations())
    // May have associations to parent entities
    assert.isAtLeast(productAssociations.length, 0)
  })

  test('should handle nested object properties with filtered schemas', async ({ assert }) => {
    const domain = new DataDomain({ key: 'test-domain', info: { name: 'Test Domain' } })
    const schemas: InMemorySchema[] = [
      // Empty address type that should be filtered
      {
        path: 'schema:AddressType',
        contents: {
          $id: 'schema:AddressType',
          type: 'object',
          title: 'AddressType',
          description: 'Address type enumeration',
        } as JSONSchema7,
      },
      // Concrete address with properties
      {
        path: 'schema:Address',
        contents: {
          $id: 'schema:Address',
          type: 'object',
          title: 'Address',
          properties: {
            street: { type: 'string' },
            city: { type: 'string' },
            country: { type: 'string' },
            type: { $ref: 'schema:AddressType' }, // References filtered schema
          },
          required: ['street', 'city'],
        } as JSONSchema7,
      },
      // User with nested address
      {
        path: 'schema:User',
        contents: {
          $id: 'schema:User',
          type: 'object',
          title: 'User',
          properties: {
            id: { type: 'string' },
            name: { type: 'string' },
            address: { $ref: 'schema:Address' }, // Nested object reference
            addresses: {
              type: 'array',
              items: { $ref: 'schema:Address' }, // Array of nested objects
            },
          },
          required: ['id', 'name'],
        } as JSONSchema7,
      },
    ]

    const importer = FilteringJsonSchemaImporter.forDatabaseModeling(domain)
    const result = await importer.import(schemas, 'NestedModel')

    const entities = Array.from(result.model.listEntities())
    const entityNames = entities.map((e) => e.info.name)

    // AddressType should be filtered
    assert.notInclude(entityNames, 'address_type')

    // Address and User should remain
    assert.include(entityNames, 'address')
    assert.include(entityNames, 'user')

    // Check that Address entity has properties
    const addressEntity = entities.find((e) => e.info.name === 'address')
    assert.isNotNull(addressEntity)
    const addressProperties = Array.from(addressEntity!.listProperties())
    assert.isAtLeast(addressProperties.length, 3) // street, city, country at minimum

    // Check that User entity has properties and associations
    const userEntity = entities.find((e) => e.info.name === 'user')
    assert.isNotNull(userEntity)
    const userProperties = Array.from(userEntity!.listProperties())
    const userAssociations = Array.from(userEntity!.listAssociations())

    assert.isAtLeast(userProperties.length, 2) // id, name at minimum
    assert.isAtLeast(userAssociations.length, 0) // May have associations to Address
  })
})

test.group('Integration Tests', () => {
  test('should maintain original functionality when no filtering is applied', async ({ assert }) => {
    const domain = new DataDomain({ key: 'test-domain', info: { name: 'Test Domain' } })
    const schemas: InMemorySchema[] = [
      {
        path: 'schema:Person',
        contents: {
          $id: 'schema:Person',
          type: 'object',
          title: 'Person',
          properties: {
            name: { type: 'string' },
            age: { type: 'integer' },
          },
          required: ['name'],
        } as JSONSchema7,
      },
    ]

    const importer = new FilteringJsonSchemaImporter(domain) // No filtering options
    const result = await importer.import(schemas, 'StandardModel')

    const entities = Array.from(result.model.listEntities())
    assert.equal(entities.length, 1)
    assert.equal(entities[0].info.name, 'person')

    const properties = Array.from(entities[0].listProperties())
    assert.equal(properties.length, 2) // name and age
  })

  test('should combine pre-filtering and post-filtering correctly', async ({ assert }) => {
    const domain = new DataDomain({ key: 'test-domain', info: { name: 'Test Domain' } })
    const schemas: InMemorySchema[] = [
      {
        path: 'schema:EmptyType',
        contents: {
          $id: 'schema:EmptyType',
          type: 'object',
          title: 'EmptyType',
        } as JSONSchema7,
      },
      {
        path: 'schema:ValidEntity',
        contents: {
          $id: 'schema:ValidEntity',
          type: 'object',
          title: 'ValidEntity',
          properties: {
            data: { type: 'string' },
          },
        } as JSONSchema7,
      },
    ]

    const importer = FilteringJsonSchemaImporter.forDatabaseModeling(domain)
    const result = await importer.import(schemas, 'CombinedModel')

    // Should have both pre-filter and post-filter messages
    const preFilterMessages = result.messages.filter((m) => m.message.includes('Pre-filtered'))
    const postFilterMessages = result.messages.filter((m) => m.message.includes('Post-filtered'))

    assert.isAtLeast(preFilterMessages.length + postFilterMessages.length, 1)

    // Only ValidEntity should remain
    const entities = Array.from(result.model.listEntities())
    assert.equal(entities.length, 1)
    assert.equal(entities[0].info.name, 'valid_entity')
  })
})
