import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
import { checkModelAvailability } from './llm';

const { mockEnv } = vi.hoisted(() => {
	return {
		mockEnv: {
			OPENAI_BASE_URL: 'http://localhost:1234/v1',
			OPENAI_API_KEY: 'test-key',
			LLM_MODEL: 'test-model'
		}
	};
});

vi.mock('$env/dynamic/private', () => ({
	env: mockEnv
}));

const mockModelsList = vi.fn();

vi.mock('openai', () => ({
	default: vi.fn(function OpenAI() {
		return {
			models: {
				list: mockModelsList
			}
		};
	})
}));

describe('checkModelAvailability', () => {
	beforeEach(() => {
		vi.clearAllMocks();
	});

	afterEach(() => {
		vi.restoreAllMocks();
	});

	it('should return available: true when model is found', async () => {
		mockModelsList.mockResolvedValue({
			data: [{ id: 'test-model' }, { id: 'gpt-4o' }, { id: 'llama2' }]
		});

		const result = await checkModelAvailability('test-model');

		expect(result).toEqual({ available: true });
		expect(mockModelsList).toHaveBeenCalledOnce();
	});

	it('should return available: false with message when model not found', async () => {
		mockModelsList.mockResolvedValue({
			data: [{ id: 'gpt-4o' }, { id: 'llama2' }]
		});

		const result = await checkModelAvailability('missing-model');

		expect(result.available).toBe(false);
		expect(result.message).toContain('Model "missing-model" not found');
		expect(result.message).toContain('Available models: gpt-4o, llama2');
	});

	it('should handle API errors gracefully', async () => {
		mockModelsList.mockRejectedValue(new Error('API connection failed'));

		const result = await checkModelAvailability('test-model');

		expect(result.available).toBe(false);
		expect(result.message).toContain('Failed to check model availability');
		expect(result.message).toContain('API connection failed');
	});

	it('should match models by exact ID (case-sensitive)', async () => {
		mockModelsList.mockResolvedValue({
			data: [{ id: 'test-model' }, { id: 'Test-Model' }]
		});

		const result1 = await checkModelAvailability('test-model');
		expect(result1.available).toBe(true);

		const result2 = await checkModelAvailability('TEST-MODEL');
		expect(result2.available).toBe(false);
	});

	it('should handle empty model list', async () => {
		mockModelsList.mockResolvedValue({
			data: []
		});

		const result = await checkModelAvailability('any-model');

		expect(result.available).toBe(false);
		expect(result.message).toContain('Available models: ');
	});
});
