import { describe, it, expect } from 'vitest'
import { compareVersions } from './utils'

describe('compareVersions', () => {
  describe('Basic version comparison', () => {
    it('should return 0 for equal versions', () => {
      expect(compareVersions('1.0.0', '1.0.0')).toBe(0)
      expect(compareVersions('14.2.1', '14.2.1')).toBe(0)
    })

    it('should return 1 when first version is greater', () => {
      expect(compareVersions('2.0.0', '1.0.0')).toBe(1)
      expect(compareVersions('1.1.0', '1.0.0')).toBe(1)
      expect(compareVersions('1.0.1', '1.0.0')).toBe(1)
      expect(compareVersions('14.3.0', '14.2.1')).toBe(1)
    })

    it('should return -1 when second version is greater', () => {
      expect(compareVersions('1.0.0', '2.0.0')).toBe(-1)
      expect(compareVersions('1.0.0', '1.1.0')).toBe(-1)
      expect(compareVersions('1.0.0', '1.0.1')).toBe(-1)
      expect(compareVersions('14.2.1', '14.3.0')).toBe(-1)
    })

    it('should handle versions with different lengths', () => {
      expect(compareVersions('1.0', '1.0.0')).toBe(0)
      expect(compareVersions('1', '1.0.0')).toBe(0)
      expect(compareVersions('1.0.1', '1.0')).toBe(1)
      expect(compareVersions('1.0', '1.0.1')).toBe(-1)
    })
  })

  describe('Alpha and Beta versions', () => {
    it('should strip alpha suffixes and compare base versions', () => {
      expect(compareVersions('14.3.0-alpha2', '14.3.0')).toBe(0)
      expect(compareVersions('14.3.0', '14.3.0-alpha2')).toBe(0)
      expect(compareVersions('14.3.0-alpha1', '14.3.0-alpha2')).toBe(0)
    })

    it('should strip beta suffixes and compare base versions', () => {
      expect(compareVersions('14.3.0-beta1', '14.3.0')).toBe(0)
      expect(compareVersions('14.3.0', '14.3.0-beta1')).toBe(0)
      expect(compareVersions('14.3.0-beta1', '14.3.0-beta2')).toBe(0)
    })

    it('should handle rc (release candidate) versions', () => {
      expect(compareVersions('14.3.0-rc1', '14.3.0')).toBe(0)
      expect(compareVersions('14.3.0-rc2', '14.3.0-rc1')).toBe(0)
    })

    it('should compare alpha versions with different base versions correctly', () => {
      expect(compareVersions('14.3.0-alpha1', '14.2.0')).toBe(1)
      expect(compareVersions('14.2.0-alpha1', '14.3.0')).toBe(-1)
      expect(compareVersions('14.3.0-alpha1', '14.3.0-beta1')).toBe(0)
    })
  })

  describe('Dev versions', () => {
    it('should treat dev versions as greater than any numeric version', () => {
      expect(compareVersions('dev/mybranch', '14.3.0')).toBe(1)
      expect(compareVersions('dev/feature', '99.99.99')).toBe(1)
      expect(compareVersions('14.3.0', 'dev/mybranch')).toBe(-1)
      expect(compareVersions('0.0.1', 'dev/test')).toBe(-1)
    })

    it('should treat all dev versions as equal', () => {
      expect(compareVersions('dev/branch1', 'dev/branch2')).toBe(0)
      expect(compareVersions('dev/feature', 'dev/feature')).toBe(0)
      expect(compareVersions('dev/a', 'dev/z')).toBe(0)
    })

    it('should handle dev versions with alpha/beta suffix correctly', () => {
      expect(compareVersions('dev/branch-alpha', '14.3.0-alpha1')).toBe(1)
      expect(compareVersions('14.3.0-beta1', 'dev/branch')).toBe(-1)
    })
  })

  describe('Build metadata', () => {
    it('should strip build metadata (+xxx)', () => {
      expect(compareVersions('14.3.0+build123', '14.3.0')).toBe(0)
      expect(compareVersions('14.3.0', '14.3.0+build456')).toBe(0)
      expect(compareVersions('14.3.0+build1', '14.3.0+build2')).toBe(0)
    })

    it('should handle versions with both pre-release and build metadata', () => {
      expect(compareVersions('14.3.0-alpha1+build123', '14.3.0')).toBe(0)
      expect(compareVersions('14.3.0-beta2+build456', '14.3.0-alpha1+build789')).toBe(0)
    })
  })

  describe('Edge cases and error handling', () => {
    it('should handle empty strings', () => {
      expect(compareVersions('', '')).toBe(0)
      expect(compareVersions('1.0.0', '')).toBe(1)
      expect(compareVersions('', '1.0.0')).toBe(-1)
    })

    it('should handle whitespace', () => {
      expect(compareVersions('  1.0.0  ', '1.0.0')).toBe(0)
      expect(compareVersions('1.0.0', '  1.0.0  ')).toBe(0)
      expect(compareVersions('  1.0.1  ', '1.0.0')).toBe(1)
      expect(compareVersions('1.0.0', '  1.0.1  ')).toBe(-1)
    })

    it('should handle malformed version strings gracefully', () => {
      expect(() => compareVersions('invalid', '1.0.0')).not.toThrow()
      expect(() => compareVersions('1.0.0', 'invalid')).not.toThrow()
      expect(() => compareVersions('x.y.z', 'a.b.c')).not.toThrow()
    })

    it('should handle versions with non-numeric parts', () => {
      expect(compareVersions('1.x.0', '1.0.0')).toBe(0) // NaN treated as 0
      expect(compareVersions('1.2.x', '1.2.0')).toBe(0)
    })

    it('should handle undefined/null-like inputs gracefully', () => {
      expect(() => compareVersions('1.0.0', '')).not.toThrow()
      expect(() => compareVersions('', '1.0.0')).not.toThrow()
    })
  })

  describe('Real-world DSS version scenarios', () => {
    it('should correctly compare DSS versions for feature gating', () => {
      // VLM feature is available in 14.3.0+
      expect(compareVersions('14.3.0', '14.3.0')).toBe(0) // equal, feature available
      expect(compareVersions('14.3.1', '14.3.0')).toBe(1) // greater, feature available
      expect(compareVersions('14.2.1', '14.3.0')).toBe(-1) // less, feature NOT available
      expect(compareVersions('15.0.0', '14.3.0')).toBe(1) // greater, feature available
    })

    it('should allow all features in dev versions', () => {
      expect(compareVersions('dev/my-feature-branch', '14.3.0') >= 0).toBe(true)
      expect(compareVersions('dev/anything', '99.99.99') >= 0).toBe(true)
    })

    it('should handle alpha versions during DSS development cycle', () => {
      // Alpha versions should be compared by base version
      expect(compareVersions('14.3.0-alpha2', '14.3.0') >= 0).toBe(true)
      expect(compareVersions('14.3.0-alpha1', '14.2.1') >= 0).toBe(true)
    })

    it('should handle real DSS version format from getAppConfig', () => {
      // Based on the actual format: { product_version: "14.2.1" }
      expect(compareVersions('14.2.1', '14.3.0')).toBe(-1)
      expect(compareVersions('14.3.0', '14.2.1')).toBe(1)
      expect(compareVersions('14.2.1', '14.2.1')).toBe(0)
    })
  })
})
