import { describe, expect, it } from 'vitest';
import { resolveAllFeatureModels, resolveFeatureModel } from '../../ai/resolve.js';
const NO_CAPS = {
    text: false,
    vision: false,
    imageGeneration: false,
    embeddings: false,
    toolCalling: false,
    structuredOutput: false,
    streaming: false,
    reasoning: false,
    longContext: false,
};
function model(id, caps, over = {}) {
    const [provider = 'anthropic', providerModelId = id] = id.split(':');
    return {
        id,
        provider: provider,
        providerModelId,
        displayName: id,
        status: 'available',
        capabilities: { ...NO_CAPS, ...caps },
        inputModalities: ['text'],
        outputModalities: ['text'],
        lastSyncedAt: '2026-01-01T00:00:00.000Z',
        source: 'provider',
        metadata: {},
        ...over,
    };
}
function conn(over = {}) {
    return {
        id: 'p-anthropic',
        provider: 'anthropic',
        displayName: 'Anthropic',
        enabled: true,
        status: 'connected',
        createdAt: '2026-01-01T00:00:00.000Z',
        updatedAt: '2026-01-01T00:00:00.000Z',
        updatedBy: 'u1',
        ...over,
    };
}
function config(over) {
    return {
        providers: over.providers ?? [conn()],
        settings: {
            defaultModelId: over.defaultModelId,
            defaultVisionModelId: over.defaultVisionModelId,
            features: over.features ?? [],
            budget: { alertAtPercentages: [], disableWhenExceeded: false },
            logsRetentionDays: 30,
        },
    };
}
const textFeature = {
    key: 'ai.features.contentWriting',
    label: 'Content writing',
    description: '',
    enabled: true,
    category: 'content',
    requiredCapabilities: ['text'],
    approvalRequired: false,
    allowBulkApply: false,
    rolesAllowed: ['ADMIN'],
    permissionsRequired: ['ai.use'],
};
describe('resolveFeatureModel', () => {
    it('uses the global default when the feature has no override', () => {
        const catalog = [model('anthropic:claude-x', { text: true })];
        const cfg = config({ defaultModelId: 'anthropic:claude-x', features: [textFeature] });
        const r = resolveFeatureModel(cfg, textFeature.key, catalog);
        expect(r.modelId).toBe('anthropic:claude-x');
        expect(r.source).toBe('global-default');
        expect(r.providerId).toBe('p-anthropic');
        expect(r.satisfiesCapabilities).toBe(true);
    });
    it('prefers the feature-level model override over the default', () => {
        const catalog = [
            model('anthropic:claude-x', { text: true }),
            model('openai:gpt-y', { text: true }, { provider: 'openai' }),
        ];
        const cfg = config({
            providers: [conn(), conn({ id: 'p-openai', provider: 'openai' })],
            defaultModelId: 'anthropic:claude-x',
            features: [{ ...textFeature, modelId: 'openai:gpt-y' }],
        });
        const r = resolveFeatureModel(cfg, textFeature.key, catalog);
        expect(r.modelId).toBe('openai:gpt-y');
        expect(r.source).toBe('feature-override');
        expect(r.providerId).toBe('p-openai');
    });
    it('falls back to the capability-typed default for a vision feature', () => {
        const visionFeature = {
            ...textFeature,
            key: 'ai.features.mediaAltText',
            requiredCapabilities: ['vision'],
        };
        const catalog = [
            model('anthropic:claude-text', { text: true }),
            model('openai:gpt-vision', { text: true, vision: true }, { provider: 'openai' }),
        ];
        const cfg = config({
            providers: [conn(), conn({ id: 'p-openai', provider: 'openai' })],
            defaultModelId: 'anthropic:claude-text', // text-only, can't satisfy vision
            defaultVisionModelId: 'openai:gpt-vision',
            features: [visionFeature],
        });
        const r = resolveFeatureModel(cfg, visionFeature.key, catalog);
        expect(r.modelId).toBe('openai:gpt-vision');
        expect(r.source).toBe('capability-default');
        expect(r.satisfiesCapabilities).toBe(true);
    });
    it('reports missing capabilities when no candidate satisfies them', () => {
        const visionFeature = {
            ...textFeature,
            key: 'ai.features.mediaAltText',
            requiredCapabilities: ['vision'],
        };
        const catalog = [model('anthropic:claude-text', { text: true })];
        const cfg = config({ defaultModelId: 'anthropic:claude-text', features: [visionFeature] });
        const r = resolveFeatureModel(cfg, visionFeature.key, catalog);
        expect(r.modelId).toBe('anthropic:claude-text');
        expect(r.satisfiesCapabilities).toBe(false);
        expect(r.missingCapabilities).toContain('vision');
    });
    it('keeps an uncatalogued override and flags it as not satisfying capabilities', () => {
        const cfg = config({
            features: [{ ...textFeature, modelId: 'anthropic:ghost-model' }],
        });
        const r = resolveFeatureModel(cfg, textFeature.key, []);
        expect(r.modelId).toBe('anthropic:ghost-model');
        expect(r.source).toBe('feature-override');
        expect(r.satisfiesCapabilities).toBe(false);
    });
    it('returns source "none" with no model configured', () => {
        const cfg = config({ features: [textFeature] });
        const r = resolveFeatureModel(cfg, textFeature.key, []);
        expect(r.source).toBe('none');
        expect(r.modelId).toBeUndefined();
        expect(r.missingCapabilities).toContain('text');
    });
    it('does not select an unavailable model when an available one exists', () => {
        const catalog = [
            model('anthropic:dead', { text: true }, { status: 'unavailable' }),
            model('anthropic:live', { text: true }),
        ];
        const cfg = config({
            defaultModelId: 'anthropic:dead',
            features: [{ ...textFeature, fallbackModelIds: ['anthropic:live'] }],
        });
        const r = resolveFeatureModel(cfg, textFeature.key, catalog);
        expect(r.modelId).toBe('anthropic:live');
        expect(r.source).toBe('fallback');
    });
    it('resolveAllFeatureModels keys by feature', () => {
        const catalog = [model('anthropic:claude-x', { text: true })];
        const cfg = config({ defaultModelId: 'anthropic:claude-x', features: [textFeature] });
        const all = resolveAllFeatureModels(cfg, catalog);
        expect(Object.keys(all)).toEqual([textFeature.key]);
        expect(all[textFeature.key]?.modelId).toBe('anthropic:claude-x');
    });
});
//# sourceMappingURL=resolve.test.js.map