import { describe, it, expect } from 'vitest'
import { loadLib } from './helpers/loadLib.js'

const { normalizeApiUrl, webRootFromApiUrl } = loadLib('url.js', [
  'normalizeApiUrl',
  'webRootFromApiUrl'
])

describe('normalizeApiUrl', () => {
  // The bug this exists for (issue #2393): the instance root was accepted and
  // stored verbatim, so every request went to /credentials instead of
  // /api/credentials. That path is a Vue router route, so the SPA catch-all
  // answered GET with 200 HTML and rejected POST with 405 — which read as a
  // backend bug rather than a URL one.
  it('appends /api to an instance root', () => {
    expect(normalizeApiUrl('http://curator.traefik.internal')).toBe(
      'http://curator.traefik.internal/api'
    )
  })

  it('leaves an API root alone rather than doubling the suffix', () => {
    expect(normalizeApiUrl('http://curator.traefik.internal/api')).toBe(
      'http://curator.traefik.internal/api'
    )
  })

  it('is idempotent', () => {
    const once = normalizeApiUrl('http://curator.example.com')
    expect(normalizeApiUrl(once)).toBe(once)
  })

  it('strips trailing slashes before deciding', () => {
    expect(normalizeApiUrl('http://curator.example.com/')).toBe('http://curator.example.com/api')
    expect(normalizeApiUrl('http://curator.example.com///')).toBe('http://curator.example.com/api')
    expect(normalizeApiUrl('http://curator.example.com/api/')).toBe('http://curator.example.com/api')
  })

  it('trims surrounding whitespace (paste artifacts)', () => {
    expect(normalizeApiUrl('  http://curator.example.com  ')).toBe(
      'http://curator.example.com/api'
    )
  })

  it('matches the /api suffix case-insensitively', () => {
    expect(normalizeApiUrl('http://curator.example.com/API')).toBe('http://curator.example.com/API')
  })

  it('returns empty string for empty/nullish input, never a bare "/api"', () => {
    // isConfigured() gates on truthiness, so a bogus '/api' here would read as
    // "configured" and produce a request against the options page's own origin.
    expect(normalizeApiUrl('')).toBe('')
    expect(normalizeApiUrl('   ')).toBe('')
    expect(normalizeApiUrl(null)).toBe('')
    expect(normalizeApiUrl(undefined)).toBe('')
  })

  it('does not treat a path merely containing "api" as the suffix', () => {
    expect(normalizeApiUrl('http://curator.example.com/apiary')).toBe(
      'http://curator.example.com/apiary/api'
    )
  })

  it('preserves a subpath deployment', () => {
    expect(normalizeApiUrl('http://host.internal/curator')).toBe('http://host.internal/curator/api')
  })
})

describe('webRootFromApiUrl', () => {
  // The SPA root, where the Vue router and the served XPI live. Used by
  // OPEN_ARTIST_PAGE and the self-update check — NOT the JSON API.
  it('strips the /api suffix', () => {
    expect(webRootFromApiUrl('http://curator.example.com/api')).toBe('http://curator.example.com')
  })

  it('accepts an instance root unchanged', () => {
    expect(webRootFromApiUrl('http://curator.example.com')).toBe('http://curator.example.com')
  })

  it('agrees with normalizeApiUrl in both directions', () => {
    for (const input of ['http://curator.example.com', 'http://curator.example.com/api']) {
      expect(normalizeApiUrl(webRootFromApiUrl(input))).toBe(normalizeApiUrl(input))
    }
  })

  it('preserves a subpath deployment', () => {
    expect(webRootFromApiUrl('http://host.internal/curator/api')).toBe('http://host.internal/curator')
  })

  it('returns empty string for empty/nullish input', () => {
    expect(webRootFromApiUrl('')).toBe('')
    expect(webRootFromApiUrl(null)).toBe('')
  })
})
