import { describe, expect, test } from 'bun:test'
import { hasFileExtension, parseSingleByteRange } from './file-serving'

describe('hasFileExtension', () => {
	describe('paths with extensions', () => {
		test('simple file extension', () => {
			expect(hasFileExtension('style.css')).toBe(true)
		})

		test('html extension', () => {
			expect(hasFileExtension('index.html')).toBe(true)
		})

		test('nested path with extension', () => {
			expect(hasFileExtension('assets/js/app.js')).toBe(true)
		})

		test('double extension', () => {
			expect(hasFileExtension('archive.tar.gz')).toBe(true)
		})

		test('dotfile with extension', () => {
			expect(hasFileExtension('.htaccess')).toBe(true)
		})

		test('minified file', () => {
			expect(hasFileExtension('bundle.min.js')).toBe(true)
		})

		test('image file', () => {
			expect(hasFileExtension('photo.png')).toBe(true)
		})

		test('sourcemap', () => {
			expect(hasFileExtension('app.js.map')).toBe(true)
		})
	})

	describe('paths without extensions (extensionless files)', () => {
		test('simple name', () => {
			expect(hasFileExtension('about')).toBe(false)
		})

		test('binary-style name with dashes', () => {
			expect(hasFileExtension('wisp-cli-x86_64-linux')).toBe(false)
		})

		test('binary-style name with underscores', () => {
			expect(hasFileExtension('my_binary_v2')).toBe(false)
		})

		test('empty string', () => {
			expect(hasFileExtension('')).toBe(false)
		})

		test('single word', () => {
			expect(hasFileExtension('README')).toBe(false)
		})

		test('path with trailing slash', () => {
			expect(hasFileExtension('somedir/')).toBe(false)
		})
	})

	describe('directory-with-dot edge cases', () => {
		test('dot in directory name, extensionless file', () => {
			expect(hasFileExtension('my.folder/file')).toBe(false)
		})

		test('dot in directory name, file with extension', () => {
			expect(hasFileExtension('my.folder/index.html')).toBe(true)
		})

		test('multiple dotted directories, extensionless file', () => {
			expect(hasFileExtension('v1.0/api.v2/handler')).toBe(false)
		})

		test('multiple dotted directories, file with extension', () => {
			expect(hasFileExtension('v1.0/api.v2/handler.js')).toBe(true)
		})
	})

	describe('trailing-dot edge case', () => {
		test('trailing dot is not a file extension', () => {
			// "file." has a dot but no alphanumeric chars after it
			expect(hasFileExtension('file.')).toBe(false)
		})
	})
})

describe('parseSingleByteRange', () => {
	test('parses bounded, open-ended, and suffix ranges', () => {
		expect(parseSingleByteRange('bytes=2-5', 10)).toEqual({ start: 2, end: 5 })
		expect(parseSingleByteRange('bytes=7-', 10)).toEqual({ start: 7, end: 9 })
		expect(parseSingleByteRange('bytes=-3', 10)).toEqual({ start: 7, end: 9 })
	})

	test('caps an end offset and rejects unsatisfiable ranges', () => {
		expect(parseSingleByteRange('bytes=8-99', 10)).toEqual({ start: 8, end: 9 })
		expect(parseSingleByteRange('bytes=10-20', 10)).toBe('unsatisfiable')
		expect(parseSingleByteRange('bytes=5-2', 10)).toBe('unsatisfiable')
	})

	test('ignores malformed or multipart syntax', () => {
		expect(parseSingleByteRange('items=0-1', 10)).toBeNull()
		expect(parseSingleByteRange('bytes=0-1,4-5', 10)).toBeNull()
	})
})
