/**
 * Example test setup and usage guide for API Client Core
 *
 * This file demonstrates how to use the testing infrastructure
 * and provides working examples for both Node.js and browser tests.
 */

// Node.js test example using Japa
import { test } from '@japa/runner'
import { TestUtils } from './test-utils.js'

// Example: Testing a utility function
test.group('Example Node.js Tests', (group) => {
  group.each.setup(() => {
    // Setup before each test
    // eslint-disable-next-line no-console
    console.log('Setting up test...')
  })

  test('should demonstrate basic testing', ({ assert }) => {
    const result = 'hello world'
    assert.equal(result, 'hello world')
    assert.typeOf(result, 'string')
  })

  test('should test async operations', async ({ assert }) => {
    const data = TestUtils.generateTestData()
    assert.typeOf(data.id, 'string')
    assert.typeOf(data.timestamp, 'number')
    assert.typeOf(data.randomBoolean, 'boolean')
  })

  test('should test HTTP mocking', async ({ assert }) => {
    const mockResponse = TestUtils.createMockResponse(200, { success: true })
    const cleanup = TestUtils.mockFetch(mockResponse)

    try {
      const response = await fetch('https://api.example.com/test')
      const data = await response.json()
      assert.isTrue(data.success)
      assert.equal(response.status, 200)
    } finally {
      cleanup()
    }
  })

  test('should test error handling', async ({ assert }) => {
    const error = await TestUtils.assertThrows(() => {
      throw new Error('Test error')
    }, 'Test error')
    assert.equal(error.message, 'Test error')
  })

  test('should validate object properties', ({ assert }) => {
    const testObj = { name: 'test', value: 42 }

    // This should not throw
    TestUtils.validateRequiredProperties(testObj, ['name', 'value'])

    // This should throw
    assert.throws(() => {
      // @ts-expect-error: Intentionally missing property
      TestUtils.validateRequiredProperties(testObj, ['name', 'missing'])
    })
  })

  test('should create test URLs with parameters', ({ assert }) => {
    const url = TestUtils.createTestUrl('/api/users', {
      page: '1',
      limit: '10',
    })

    assert.equal(url.pathname, '/api/users')
    assert.equal(url.searchParams.get('page'), '1')
    assert.equal(url.searchParams.get('limit'), '10')
  })

  test('should create test requests', ({ assert }) => {
    const request = TestUtils.createTestRequest(
      'POST',
      'https://api.example.com/users',
      JSON.stringify({ name: 'John' }),
      { Authorization: 'Bearer token123' }
    )

    assert.equal(request.method, 'POST')
    assert.equal(request.url, 'https://api.example.com/users')
  })

  test('should create mock auth config', ({ assert }) => {
    const config = TestUtils.createMockAuthConfig()
    assert.typeOf(config.clientId, 'string')
    assert.typeOf(config.clientSecret, 'string')
    assert.isArray(config.scopes)
    assert.include(config.scopes, 'read')
    assert.include(config.scopes, 'write')
  })

  test('should test with sinon mocks', ({ sinon, assert }) => {
    const mockObj = {
      getValue: () => 'original',
    }

    const stub = sinon.stub(mockObj, 'getValue')
    stub.returns('mocked')

    assert.equal(mockObj.getValue(), 'mocked')

    stub.restore()
    assert.equal(mockObj.getValue(), 'original')
  })

  test('should test timeout behavior', async ({ assert }) => {
    const start = Date.now()
    await TestUtils.sleep(100)
    const elapsed = Date.now() - start

    assert.isAtLeast(elapsed, 90) // Allow some variance
    assert.isAtMost(elapsed, 150)
  })
})

export default {
  setupNodeTests: () => {
    // eslint-disable-next-line no-console
    console.log('Node.js test environment initialized')
  },

  setupBrowserTests: () => {
    // eslint-disable-next-line no-console
    console.log('Browser test environment initialized')
  },
}
