/**
 * test/complex_test.ets
 *
 * Comprehensive tests for complex features:
 * - Map fields (string->string, string->int32, string->message, int32->string)
 * - Oneof fields
 * - Nested messages
 * - Repeated messages
 * - All scalar types
 * - Enums
 */

import { ComplexMessage } from '../test-output/test/messages/ComplexMessage'
import { Metadata } from '../test-output/test/messages/Metadata'
import { NestedData } from '../test-output/test/messages/NestedData'
import { Status } from '../test-output/test/enums/Status'

console.log('=== Complex Features Test Suite ===\n')

// Test 1: Map fields
console.log('Test 1: Map Fields')
const msg1 = ComplexMessage.create({
  id: 'test-001',
  properties: new Map([
    ['env', 'production'],
    ['region', 'us-west-1'],
    ['version', '2.0.0']
  ]),
  counters: new Map([
    ['requests', 1000],
    ['errors', 5],
    ['success', 995]
  ]),
  metadataMap: new Map([
    ['meta1', Metadata.create({ key: 'k1', value: 'v1', timestamp: 1234567890n })],
    ['meta2', Metadata.create({ key: 'k2', value: 'v2', timestamp: 9876543210n })]
  ]),
  idToName: new Map([
    [1, 'Alice'],
    [2, 'Bob'],
    [3, 'Charlie']
  ])
})

console.log('  properties.size:', msg1.properties.size)
console.log('  counters.size:', msg1.counters.size)
console.log('  metadataMap.size:', msg1.metadataMap.size)
console.log('  idToName.size:', msg1.idToName.size)

const binary1 = msg1.toBinary()
console.log('  Binary length:', binary1.length)

const decoded1 = ComplexMessage.fromBinary(binary1)
console.log('  Decoded properties.size:', decoded1.properties.size)
console.log('  Decoded counters.get("requests"):', decoded1.counters.get('requests'))
console.log('  Decoded metadataMap.get("meta1").key:', decoded1.metadataMap.get('meta1')?.key)
console.log('  Decoded idToName.get(2):', decoded1.idToName.get(2))
console.log('  ✅ Map fields work!\n')

// Test 2: Oneof fields
console.log('Test 2: Oneof Fields')
const msg2a = ComplexMessage.create({
  id: 'test-002a',
  payload: { kind: 'textPayload', textPayload: 'Hello World' }
})
console.log('  Text payload:', msg2a.payload?.kind === 'textPayload' ? msg2a.payload.textPayload : 'N/A')

const binary2a = msg2a.toBinary()
const decoded2a = ComplexMessage.fromBinary(binary2a)
console.log('  Decoded payload kind:', decoded2a.payload?.kind)
console.log('  Decoded payload value:', decoded2a.payload?.kind === 'textPayload' ? decoded2a.payload.textPayload : 'N/A')

const msg2b = ComplexMessage.create({
  id: 'test-002b',
  payload: { kind: 'numericPayload', numericPayload: 42 }
})
const binary2b = msg2b.toBinary()
const decoded2b = ComplexMessage.fromBinary(binary2b)
console.log('  Numeric payload:', decoded2b.payload?.kind === 'numericPayload' ? decoded2b.payload.numericPayload : 'N/A')

const msg2c = ComplexMessage.create({
  id: 'test-002c',
  payload: { kind: 'binaryPayload', binaryPayload: new Uint8Array([0x01, 0x02, 0x03, 0xFF]) }
})
const binary2c = msg2c.toBinary()
const decoded2c = ComplexMessage.fromBinary(binary2c)
console.log('  Binary payload length:', decoded2c.payload?.kind === 'binaryPayload' ? decoded2c.payload.binaryPayload.length : 0)
console.log('  ✅ Oneof fields work!\n')

// Test 3: Nested messages
console.log('Test 3: Nested Messages')
const msg3 = ComplexMessage.create({
  id: 'test-003',
  nested: NestedData.create({ name: 'nested-1', value: 100 }),
  metadataList: [
    Metadata.create({ key: 'k1', value: 'v1', timestamp: 111n }),
    Metadata.create({ key: 'k2', value: 'v2', timestamp: 222n }),
    Metadata.create({ key: 'k3', value: 'v3', timestamp: 333n })
  ]
})

console.log('  nested.name:', msg3.nested?.name)
console.log('  metadataList.length:', msg3.metadataList.length)

const binary3 = msg3.toBinary()
const decoded3 = ComplexMessage.fromBinary(binary3)
console.log('  Decoded nested.name:', decoded3.nested?.name)
console.log('  Decoded nested.value:', decoded3.nested?.value)
console.log('  Decoded metadataList[1].key:', decoded3.metadataList[1]?.key)
console.log('  ✅ Nested messages work!\n')

// Test 4: Recursive messages (deep nesting)
console.log('Test 4: Recursive Messages')
const msg4 = ComplexMessage.create({
  id: 'parent',
  count: 1,
  child: ComplexMessage.create({
    id: 'child-1',
    count: 2,
    child: ComplexMessage.create({
      id: 'child-2',
      count: 3,
      child: ComplexMessage.create({
        id: 'child-3',
        count: 4
      })
    })
  })
})

console.log('  Root id:', msg4.id)
console.log('  Child id:', msg4.child?.id)
console.log('  Grandchild id:', msg4.child?.child?.id)
console.log('  Great-grandchild id:', msg4.child?.child?.child?.id)

const binary4 = msg4.toBinary()
console.log('  Binary length:', binary4.length)
const decoded4 = ComplexMessage.fromBinary(binary4)
console.log('  Decoded root id:', decoded4.id)
console.log('  Decoded child id:', decoded4.child?.id)
console.log('  Decoded grandchild id:', decoded4.child?.child?.id)
console.log('  Decoded great-grandchild id:', decoded4.child?.child?.child?.id)
console.log('  ✅ Recursive messages work!\n')

// Test 5: All scalar types
console.log('Test 5: All Scalar Types')
const msg5 = ComplexMessage.create({
  id: 'scalar-test',
  count: 42,
  bigNumber: 9223372036854775807n,  // Max int64
  price: 99.99,
  active: true,
  data: new Uint8Array([0xDE, 0xAD, 0xBE, 0xEF]),
  status: Status.ACTIVE,
  tags: ['tag1', 'tag2', 'tag3'],
  numbers: [1, 2, 3, 4, 5]
})

console.log('  id:', msg5.id)
console.log('  count:', msg5.count)
console.log('  bigNumber:', msg5.bigNumber)
console.log('  price:', msg5.price)
console.log('  active:', msg5.active)
console.log('  data.length:', msg5.data.length)
console.log('  status:', Status[msg5.status as number])
console.log('  tags.length:', msg5.tags.length)
console.log('  numbers.length:', msg5.numbers.length)

const binary5 = msg5.toBinary()
console.log('  Binary length:', binary5.length)
const decoded5 = ComplexMessage.fromBinary(binary5)
console.log('  Decoded count:', decoded5.count)
console.log('  Decoded bigNumber:', decoded5.bigNumber)
console.log('  Decoded price:', decoded5.price)
console.log('  Decoded active:', decoded5.active)
console.log('  Decoded data:', Array.from(decoded5.data).map(b => '0x' + b.toString(16).toUpperCase()).join(' '))
console.log('  Decoded status:', Status[decoded5.status as number])
console.log('  ✅ All scalar types work!\n')

// Test 6: Validation
console.log('Test 6: Validation')
const validMsg = ComplexMessage.create({
  id: 'valid-001',
  nested: NestedData.create({ name: 'test', value: 1 }),
  metadataList: [
    Metadata.create({ key: 'k1', value: 'v1', timestamp: 123n })
  ]
})

const validationResult = validMsg.validate()
console.log('  Validation result:', validationResult === null ? 'PASS' : validationResult)
console.log('  ✅ Validation works!\n')

// Test 7: Clear and isEmpty
console.log('Test 7: Clear and isEmpty')
const msg7 = ComplexMessage.create({
  id: 'test-007',
  count: 100,
  tags: ['a', 'b'],
  properties: new Map([['key', 'value']])
})

console.log('  Before clear - isEmpty:', msg7.isEmpty())
console.log('  Before clear - id:', msg7.id)
console.log('  Before clear - count:', msg7.count)

msg7.clear()
console.log('  After clear - isEmpty:', msg7.isEmpty())
console.log('  After clear - id:', msg7.id)
console.log('  After clear - count:', msg7.count)
console.log('  After clear - tags.length:', msg7.tags.length)
console.log('  After clear - properties.size:', msg7.properties.size)
console.log('  ✅ Clear and isEmpty work!\n')

// Test 8: Clone and equals
console.log('Test 8: Clone and Equals')
const msg8 = ComplexMessage.create({
  id: 'test-008',
  count: 500,
  properties: new Map([['env', 'test']]),
  nested: NestedData.create({ name: 'nested', value: 99 })
})

const cloned8 = msg8.clone()
console.log('  Original id:', msg8.id)
console.log('  Cloned id:', cloned8.id)
console.log('  Are equal:', msg8.equals(cloned8))

cloned8.count = 999
console.log('  After modification - Original count:', msg8.count)
console.log('  After modification - Cloned count:', cloned8.count)
console.log('  After modification - Are equal:', msg8.equals(cloned8))
console.log('  ✅ Clone and equals work!\n')

console.log('=== All Complex Features Tests Passed! ✅ ===')