import { test } from '@japa/runner'
import {
  SemanticType,
  DataSemantics,
  isPropertySemantic,
  SemanticCategory,
  SemanticScope,
  SemanticTiming,
  SemanticOperation,
} from '../../../src/modeling/Semantics.js'

test.group('Username Semantic', () => {
  test('should exist in SemanticType enum', ({ assert }) => {
    assert.equal(SemanticType.Username, 'Semantic#Username')
  })

  test('should exist in DataSemantics registry', ({ assert }) => {
    const semantic = DataSemantics[SemanticType.Username]
    assert.isDefined(semantic)
    assert.equal(semantic.id, SemanticType.Username)
  })

  test('should be a property semantic', ({ assert }) => {
    const semantic = DataSemantics[SemanticType.Username]
    assert.isTrue(isPropertySemantic(semantic))
    assert.equal(semantic.scope, SemanticScope.Property)
  })

  test('should have correct display name and description', ({ assert }) => {
    const semantic = DataSemantics[SemanticType.Username]
    assert.equal(semantic.displayName, 'Username')
    assert.equal(semantic.description, 'User authentication identifier')
  })

  test('should be in Identity category', ({ assert }) => {
    const semantic = DataSemantics[SemanticType.Username]
    assert.equal(semantic.category, SemanticCategory.Identity)
  })

  test('should only apply to string data types', ({ assert }) => {
    const semantic = DataSemantics[SemanticType.Username]
    if (isPropertySemantic(semantic)) {
      assert.deepEqual(semantic.applicableDataTypes, ['string'])
    }
  })

  test('should not have configuration', ({ assert }) => {
    const semantic = DataSemantics[SemanticType.Username]
    assert.isFalse(semantic.hasConfig)
  })

  test('should not be disableable for security reasons', ({ assert }) => {
    const semantic = DataSemantics[SemanticType.Username]
    assert.isFalse(semantic.runtime.canDisable)
  })

  test('should have correct runtime configuration', ({ assert }) => {
    const semantic = DataSemantics[SemanticType.Username]
    const runtime = semantic.runtime

    assert.equal(runtime.timing, SemanticTiming.Before)
    assert.deepEqual(runtime.operations, [SemanticOperation.Create, SemanticOperation.Update, SemanticOperation.Read])
    assert.equal(runtime.priority, 15) // High priority for authentication
    assert.equal(runtime.timeoutMs, 100) // Fast operation
  })

  test('should have higher priority than general user properties but lower than password', ({ assert }) => {
    const usernameSemantic = DataSemantics[SemanticType.Username]
    const passwordSemantic = DataSemantics[SemanticType.Password]
    const userRoleSemantic = DataSemantics[SemanticType.UserRole]

    const usernameP = usernameSemantic.runtime.priority ?? 100
    const passwordP = passwordSemantic.runtime.priority ?? 100
    const userRoleP = userRoleSemantic.runtime.priority ?? 100

    // Username should have lower priority number (higher priority) than UserRole
    assert.isAtMost(usernameP, userRoleP)
    // But higher priority number (lower priority) than Password
    assert.isAtLeast(usernameP, passwordP)
  })
})
