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

import { formatVertexApiHost, maskApiKey, routeToEndpoint, splitApiKeyString, validateApiHost } from '../api'

describe('api', () => {
  describe('maskApiKey', () => {
    it('should return empty string when key is empty', () => {
      expect(maskApiKey('')).toBe('')
      expect(maskApiKey(null as unknown as string)).toBe('')
      expect(maskApiKey(undefined as unknown as string)).toBe('')
    })

    it('should mask keys longer than 24 characters', () => {
      const key = '1234567890abcdefghijklmnopqrstuvwxyz'
      expect(maskApiKey(key)).toBe('12345678****stuvwxyz')
    })

    it('should mask keys longer than 16 characters but not longer than 24', () => {
      const key = '1234567890abcdefgh'
      expect(maskApiKey(key)).toBe('1234****efgh')
    })

    it('should mask keys longer than 8 characters but not longer than 16', () => {
      const key = '1234567890'
      expect(maskApiKey(key)).toBe('12****90')
    })

    it('should not mask keys that are 8 characters or shorter', () => {
      expect(maskApiKey('12345678')).toBe('12345678')
      expect(maskApiKey('123')).toBe('123')
    })

    it('should handle keys at exactly the boundary conditions', () => {
      // 24 characters
      expect(maskApiKey('123456789012345678901234')).toBe('1234****1234')

      // 16 characters
      expect(maskApiKey('1234567890123456')).toBe('12****56')

      // 8 characters
      expect(maskApiKey('12345678')).toBe('12345678')
    })
  })

  describe('splitApiKeyString', () => {
    it('should split comma-separated keys', () => {
      const input = 'key1,key2,key3'
      const result = splitApiKeyString(input)
      expect(result).toEqual(['key1', 'key2', 'key3'])
    })

    it('should trim spaces around keys', () => {
      const input = ' key1 , key2 ,key3 '
      const result = splitApiKeyString(input)
      expect(result).toEqual(['key1', 'key2', 'key3'])
    })

    it('should handle escaped commas', () => {
      const input = 'key1,key2\\,withcomma,key3'
      const result = splitApiKeyString(input)
      expect(result).toEqual(['key1', 'key2,withcomma', 'key3'])
    })

    it('should handle multiple escaped commas', () => {
      const input = 'key1\\,withcomma1,key2\\,withcomma2'
      const result = splitApiKeyString(input)
      expect(result).toEqual(['key1,withcomma1', 'key2,withcomma2'])
    })

    it('should ignore empty keys', () => {
      const input = 'key1,,key2, ,key3'
      const result = splitApiKeyString(input)
      expect(result).toEqual(['key1', 'key2', 'key3'])
    })

    it('should return empty array for empty string', () => {
      const input = ''
      const result = splitApiKeyString(input)
      expect(result).toEqual([])
    })

    it('should handle only one key', () => {
      const input = 'singlekey'
      const result = splitApiKeyString(input)
      expect(result).toEqual(['singlekey'])
    })

    it('should handle only escaped comma', () => {
      const input = 'key\\,withcomma'
      const result = splitApiKeyString(input)
      expect(result).toEqual(['key,withcomma'])
    })

    it('should handle all keys with spaces and escaped commas', () => {
      const input = ' key1 , key2\\,withcomma , key3 '
      const result = splitApiKeyString(input)
      expect(result).toEqual(['key1', 'key2,withcomma', 'key3'])
    })
  })

  describe('validateApiHost', () => {
    it('accepts empty or whitespace-only host', () => {
      expect(validateApiHost('')).toBe(true)
      expect(validateApiHost('   ')).toBe(true)
    })

    it('rejects unsupported protocols', () => {
      expect(validateApiHost('ftp://api.example.com')).toBe(false)
    })

    it('validates supported endpoint fragments when using hash suffix', () => {
      expect(validateApiHost('https://api.example.com/v1/chat/completions#')).toBe(true)
      expect(validateApiHost('https://api.example.com/v1/unknown#')).toBe(true)
    })
  })

  describe('routeToEndpoint', () => {
    it('returns host without endpoint when not using hash suffix', () => {
      expect(routeToEndpoint(' https://api.example.com/v1 ')).toEqual({
        baseURL: 'https://api.example.com/v1',
        endpoint: ''
      })
    })

    it('extracts known endpoint and base url when using hash suffix', () => {
      expect(routeToEndpoint('https://api.example.com/v1/chat/completions#')).toEqual({
        baseURL: 'https://api.example.com/v1',
        endpoint: 'chat/completions'
      })
    })

    it('returns empty endpoint when unsupported endpoint fragment is provided', () => {
      expect(routeToEndpoint('https://api.example.com/v1/custom#')).toEqual({
        baseURL: 'https://api.example.com/v1/custom',
        endpoint: ''
      })
    })

    it('prefers the most specific endpoint match when multiple matches exist', () => {
      expect(routeToEndpoint('https://api.example.com/v1/streamGenerateContent#')).toEqual({
        baseURL: 'https://api.example.com/v1',
        endpoint: 'streamGenerateContent'
      })
    })

    it('extract OpenAI images generations endpoint', () => {
      expect(routeToEndpoint('https://open.cherryin.net/v1/images/generations#')).toEqual({
        baseURL: 'https://open.cherryin.net/v1',
        endpoint: 'images/generations'
      })
    })

    it('extract Gemini images generation endpoint', () => {
      expect(routeToEndpoint('https://open.cherryin.net/v1beta/models/imagen-4.0-generate-001:predict#')).toEqual({
        baseURL: 'https://open.cherryin.net/v1beta/models/imagen-4.0-generate-001',
        endpoint: 'predict'
      })
    })
  })

  describe('formatVertexApiHost', () => {
    const baseInput = { project: 'test-project', location: 'us-central1' }

    it('builds default google endpoint when host absent', () => {
      expect(formatVertexApiHost({ ...baseInput, apiHost: '' })).toBe(
        'https://us-central1-aiplatform.googleapis.com/v1/projects/test-project/locations/us-central1'
      )
    })

    it('prefers default endpoint when host ends with google domain', () => {
      expect(formatVertexApiHost({ ...baseInput, apiHost: 'https://aiplatform.googleapis.com' })).toBe(
        'https://us-central1-aiplatform.googleapis.com/v1/projects/test-project/locations/us-central1'
      )
    })

    it('appends api version to custom host', () => {
      expect(formatVertexApiHost({ ...baseInput, apiHost: 'https://custom.googleapis.com/vertex' })).toBe(
        'https://custom.googleapis.com/vertex/v1'
      )
    })

    it('uses global endpoint when location equals global', () => {
      expect(formatVertexApiHost({ project: 'global-project', location: 'global', apiHost: '' })).toBe(
        'https://aiplatform.googleapis.com/v1/projects/global-project/locations/global'
      )
    })
  })
})
