import { describe, test, expect } from 'bun:test'

const { normalizePayload } = await import('../services/transport')

// extractContent is not exported; we test it via normalizePayload's content field

// =============================================================================
// extractContent (via normalizePayload content field)
// =============================================================================

describe('extractContent', () => {
  test('returns empty string for null payload', () => {
    const result = normalizePayload('assistant', null)
    expect(result.content).toBe('')
  })

  test('returns empty string for undefined payload', () => {
    const result = normalizePayload('assistant', undefined)
    expect(result.content).toBe('')
  })

  test('returns the string for string payload', () => {
    const result = normalizePayload('assistant', 'hello world')
    expect(result.content).toBe('hello world')
  })

  test('extracts content field from object payload', () => {
    const result = normalizePayload('assistant', { content: 'direct content' })
    expect(result.content).toBe('direct content')
  })

  test('extracts message.content string from object payload', () => {
    const result = normalizePayload('assistant', {
      message: { content: 'msg content' },
    })
    expect(result.content).toBe('msg content')
  })

  test('extracts text blocks from message.content array', () => {
    const payload = {
      message: {
        content: [
          { type: 'text', text: 'Hello ' },
          { type: 'text', text: 'World' },
        ],
      },
    }
    const result = normalizePayload('assistant', payload)
    expect(result.content).toBe('Hello World')
  })

  test('ignores non-text blocks in message.content array', () => {
    const payload = {
      message: {
        content: [
          { type: 'image', url: 'http://example.com/img.png' },
          { type: 'text', text: 'only this' },
        ],
      },
    }
    const result = normalizePayload('assistant', payload)
    expect(result.content).toBe('only this')
  })

  test('returns empty string when no extractable content', () => {
    const result = normalizePayload('assistant', { foo: 'bar' })
    expect(result.content).toBe('')
  })

  test('prefers direct content over message.content', () => {
    const result = normalizePayload('assistant', {
      content: 'direct',
      message: { content: 'nested' },
    })
    expect(result.content).toBe('direct')
  })
})

// =============================================================================
// normalizePayload — field preservation
// =============================================================================

describe('normalizePayload — field preservation', () => {
  test('preserves raw payload', () => {
    const payload = { content: 'test', extra: true }
    const result = normalizePayload('assistant', payload)
    expect(result.raw).toBe(payload)
  })

  test('preserves uuid field', () => {
    const result = normalizePayload('assistant', { uuid: 'u-123' })
    expect(result.uuid).toBe('u-123')
  })

  test('does not preserve uuid when empty string', () => {
    const result = normalizePayload('assistant', { uuid: '' })
    expect(result.uuid).toBeUndefined()
  })

  test('preserves isSynthetic boolean', () => {
    const result = normalizePayload('assistant', { isSynthetic: true })
    expect(result.isSynthetic).toBe(true)
  })

  test('preserves status string', () => {
    const result = normalizePayload('assistant', { status: 'running' })
    expect(result.status).toBe('running')
  })

  test('preserves subtype string', () => {
    const result = normalizePayload('assistant', { subtype: 'progress' })
    expect(result.subtype).toBe('progress')
  })

  test('preserves tool_name from tool_name field', () => {
    const result = normalizePayload('tool', { tool_name: 'bash' })
    expect(result.tool_name).toBe('bash')
  })

  test('preserves tool_name from name field', () => {
    const result = normalizePayload('tool', { name: 'read' })
    expect(result.tool_name).toBe('read')
  })

  test('preserves tool_input from tool_input field', () => {
    const input = { command: 'ls' }
    const result = normalizePayload('tool', { tool_input: input })
    expect(result.tool_input).toEqual(input)
  })

  test('preserves tool_input from input field', () => {
    const input = { path: '/tmp' }
    const result = normalizePayload('tool', { input })
    expect(result.tool_input).toEqual(input)
  })

  test('preserves request_id', () => {
    const result = normalizePayload('permission', { request_id: 'req-1' })
    expect(result.request_id).toBe('req-1')
  })

  test('preserves request object', () => {
    const req = { subtype: 'permission' }
    const result = normalizePayload('permission', { request: req })
    expect(result.request).toEqual(req)
  })

  test('preserves approved field', () => {
    const result = normalizePayload('permission', { approved: true })
    expect(result.approved).toBe(true)
  })

  test('preserves updated_input', () => {
    const input = { command: 'rm -rf' }
    const result = normalizePayload('permission', { updated_input: input })
    expect(result.updated_input).toEqual(input)
  })

  test('preserves message field for backward compat', () => {
    const msg = { role: 'user', content: 'hi' }
    const result = normalizePayload('assistant', { message: msg })
    expect(result.message).toEqual(msg)
  })
})

// =============================================================================
// normalizePayload — task_state special handling
// =============================================================================

describe('normalizePayload — task_state type', () => {
  test('preserves task_list_id (snake_case)', () => {
    const result = normalizePayload('task_state', { task_list_id: 'tl-1' })
    expect(result.task_list_id).toBe('tl-1')
  })

  test('preserves taskListId (camelCase)', () => {
    const result = normalizePayload('task_state', { taskListId: 'tl-2' })
    expect(result.taskListId).toBe('tl-2')
  })

  test('preserves tasks array', () => {
    const tasks = [{ id: 't1', title: 'Task 1' }]
    const result = normalizePayload('task_state', { tasks })
    expect(result.tasks).toEqual(tasks)
  })

  test('does not preserve task fields for non-task_state type', () => {
    const result = normalizePayload('assistant', {
      task_list_id: 'tl-1',
      taskListId: 'tl-2',
      tasks: [],
    })
    expect(result.task_list_id).toBeUndefined()
    expect(result.taskListId).toBeUndefined()
    expect(result.tasks).toBeUndefined()
  })
})
