import { describe, it, expect } from 'vitest'

import { config, apiUrl } from './config'

describe('config', () => {
  it('exports required configuration properties', () => {
    /**
     * Test that the config object contains all required properties.
     *
     * The API client, Socket.IO client, and OAuth flow all depend on
     * these configuration values being present. Missing values would
     * cause runtime errors in those modules.
     */
    expect(config).toHaveProperty('apiBaseUrl')
    expect(config).toHaveProperty('wsUrl')
    expect(config).toHaveProperty('oauthRedirectUri')
    expect(config).toHaveProperty('isDev')
    expect(config).toHaveProperty('isProd')
  })

  it('has string values for URL properties', () => {
    /**
     * Test that URL configuration values are strings.
     *
     * URL properties must be strings to be used in fetch() calls
     * and Socket.IO connection. Non-string values would cause
     * type errors or runtime failures.
     */
    expect(typeof config.apiBaseUrl).toBe('string')
    expect(typeof config.wsUrl).toBe('string')
    expect(typeof config.oauthRedirectUri).toBe('string')
  })

  it('has boolean values for environment flags', () => {
    /**
     * Test that environment flags are booleans.
     *
     * isDev and isProd are used in conditional logic throughout
     * the app. They must be booleans for correct behavior in
     * if statements and ternary expressions.
     */
    expect(typeof config.isDev).toBe('boolean')
    expect(typeof config.isProd).toBe('boolean')
  })

  it('has mutually exclusive isDev and isProd flags', () => {
    /**
     * Test that isDev and isProd are mutually exclusive.
     *
     * The app should never be in both development and production
     * mode simultaneously. This would cause confusing behavior
     * with logging, error handling, and API endpoints.
     */
    expect(config.isDev).not.toBe(config.isProd)
  })
})

describe('apiUrl', () => {
  it('builds full URL from path with leading slash', () => {
    /**
     * Test that apiUrl correctly combines base URL and path.
     *
     * API calls use paths like '/api/users/me'. The apiUrl helper
     * must correctly join these with the base URL without double
     * slashes or missing slashes.
     */
    const url = apiUrl('/api/users/me')

    expect(url).toBe(`${config.apiBaseUrl}/api/users/me`)
  })

  it('builds full URL from path without leading slash', () => {
    /**
     * Test that apiUrl handles paths without leading slashes.
     *
     * Some code may pass paths without leading slashes. The helper
     * should normalize these to produce correct URLs.
     */
    const url = apiUrl('api/users/me')

    expect(url).toBe(`${config.apiBaseUrl}/api/users/me`)
  })

  it('handles base URL with trailing slash', () => {
    /**
     * Test that apiUrl doesn't create double slashes in the path.
     *
     * If the base URL ends with a slash and the path starts with one,
     * we'd get double slashes (e.g., http://localhost:8000//api).
     * The helper should prevent this.
     */
    const url = apiUrl('/api/test')

    // Remove protocol prefix, then check for double slashes
    const urlWithoutProtocol = url.replace(/^https?:\/\//, '')
    expect(urlWithoutProtocol).not.toContain('//')
  })
})
