import { z } from 'zod';
import { createCommand } from '../../../types';
import * as tui from '../../../tui';
import { getCommand } from '../../../command-prefix';
import { getExecutingAgent } from '../../../agent-detection';
import { createPublicAIGatewayService, getAIGatewayUrl } from './util';
import { getCachedAIGatewayModels, setCachedAIGatewayModels } from './model-cache';
const ModelRowSchema = z.object({
    provider: z.string(),
    id: z.string(),
    name: z.string(),
    api: z.string().optional(),
    reasoning: z.boolean().optional(),
    contextWindow: z.number().optional(),
    maxOutputTokens: z.number().optional(),
});
const ModelsResponseSchema = z.object({
    models: z.array(ModelRowSchema),
    count: z.number(),
    model: ModelRowSchema.nullable().optional(),
});
const recommendedModels = [
    { use: 'fast', candidates: ['openai/gpt-4o-mini', 'openai/gpt-4.1-mini'] },
    { use: 'reasoning', candidates: ['openai/gpt-5-mini', 'openai/o4-mini'] },
    { use: 'coding', candidates: ['anthropic/claude-opus-4-7', 'openai/gpt-5-codex'] },
    { use: 'cheap', candidates: ['openai/gpt-4.1-nano', 'openai/gpt-5-nano'] },
];
function isAgentOutputMode() {
    return Boolean(getExecutingAgent()) && process.env.AGENTUITY_AIGATEWAY_AGENT_OUTPUT !== 'false';
}
function getRecommendations(rows) {
    const byId = new Map(rows.map((row) => [normalizeModelId(row.id), row]));
    return recommendedModels
        .map((rec) => {
        const model = rec.candidates.map((id) => byId.get(normalizeModelId(id))).find(Boolean);
        return model ? { use: rec.use, model: model.id, name: model.name } : undefined;
    })
        .filter((row) => Boolean(row));
}
function normalizeModelId(id) {
    const normalized = id.toLowerCase();
    const parts = normalized.split('/');
    return parts.length > 1 ? (parts.at(-1) ?? normalized) : normalized;
}
function matchesProviderFilter(provider, modelId, providerFilter) {
    if (!providerFilter) {
        return true;
    }
    return provider === providerFilter || modelId.startsWith(`${providerFilter}/`);
}
function matchesModelFilter(provider, modelId, modelFilter) {
    if (!modelFilter) {
        return true;
    }
    return modelId === modelFilter || `${provider}/${modelId}` === modelFilter;
}
function matchesNameFilter(modelId, modelName, nameFilter) {
    if (!nameFilter) {
        return true;
    }
    const normalized = nameFilter.toLowerCase();
    return (modelId.toLowerCase() === normalized ||
        modelId.split('/').pop()?.toLowerCase() === normalized ||
        modelName.toLowerCase() === normalized);
}
export const modelsSubcommand = createCommand({
    name: 'models',
    aliases: ['list', 'ls'],
    description: 'List AI Gateway models',
    tags: ['read-only', 'fast'],
    idempotent: true,
    examples: [
        { command: getCommand('cloud aigateway models'), description: 'List all models' },
        {
            command: getCommand('cloud aigateway models --provider openai'),
            description: 'List OpenAI models',
        },
        {
            command: getCommand('cloud aigateway models --model anthropic/claude-opus-4-7'),
            description: 'Show one model by id',
        },
    ],
    schema: {
        options: z.object({
            model: z.string().optional().describe('show one model by full provider/id'),
            provider: z.string().optional().describe('filter by provider'),
            name: z
                .string()
                .optional()
                .describe('show one model by id or display name with --provider'),
            reasoning: z.boolean().optional().describe('only show reasoning models'),
            input: z.string().optional().describe('filter by input modality, such as text or image'),
            output: z.string().optional().describe('filter by output modality, such as text or image'),
            ids: z.boolean().optional().describe('only print model ids'),
            simple: z.boolean().optional().describe('print a compact model list'),
            recommended: z.boolean().optional().describe('show recommended models for common uses'),
            refreshModels: z
                .boolean()
                .optional()
                .describe('refresh the cached AI Gateway model catalog'),
        }),
        response: ModelsResponseSchema,
    },
    async handler(ctx) {
        const service = createPublicAIGatewayService(ctx);
        const profile = ctx.config?.name ?? 'default';
        const cacheKey = getAIGatewayUrl(ctx.region, ctx.config?.overrides);
        const cached = ctx.opts.refreshModels
            ? null
            : await getCachedAIGatewayModels(profile, cacheKey);
        const catalog = cached ?? (await service.listModels());
        if (!cached) {
            await setCachedAIGatewayModels(profile, cacheKey, catalog);
        }
        const rows = Object.entries(catalog).flatMap(([provider, models]) => models
            .filter((model) => matchesProviderFilter(provider, model.id, ctx.opts.provider))
            .filter((model) => matchesModelFilter(provider, model.id, ctx.opts.model))
            .filter((model) => matchesNameFilter(model.id, model.name, ctx.opts.name))
            .filter((model) => !ctx.opts.reasoning || model.reasoning)
            .filter((model) => !ctx.opts.input || model.input_modalities?.includes(ctx.opts.input))
            .filter((model) => !ctx.opts.output || model.output_modalities?.includes(ctx.opts.output))
            .map((model) => ({
            provider,
            id: model.id,
            name: model.name,
            api: model.api,
            reasoning: model.reasoning,
            contextWindow: model.context_window,
            maxOutputTokens: model.max_output_tokens,
        })));
        const singleLookup = Boolean(ctx.opts.model || ctx.opts.name);
        const selectedModel = singleLookup ? (rows[0] ?? null) : undefined;
        const agentOutput = isAgentOutputMode();
        if (ctx.options.json || agentOutput) {
            if (agentOutput && !ctx.options.json) {
                if (ctx.opts.ids) {
                    console.log(JSON.stringify({ ids: rows.map((row) => row.id), count: rows.length }, null, 2));
                }
                else if (ctx.opts.recommended) {
                    console.log(JSON.stringify({ recommendations: getRecommendations(rows) }, null, 2));
                }
                else if (singleLookup) {
                    console.log(JSON.stringify({ model: selectedModel, models: rows, count: rows.length }, null, 2));
                }
                else {
                    console.log(JSON.stringify({ models: rows, count: rows.length }, null, 2));
                }
            }
        }
        else {
            if (rows.length === 0) {
                tui.info('No AI Gateway models found');
            }
            else if (ctx.opts.ids) {
                for (const row of rows) {
                    console.log(row.id);
                }
            }
            else if (ctx.opts.recommended) {
                const recommendations = getRecommendations(rows).map((row) => ({
                    Use: row.use,
                    Model: row.model,
                    Name: row.name,
                }));
                if (recommendations.length === 0) {
                    tui.info('No recommended AI Gateway models found');
                }
                else {
                    tui.table(recommendations, ['Use', 'Model', 'Name']);
                }
            }
            else if (ctx.opts.simple) {
                tui.table(rows.map((row) => ({
                    Model: row.id,
                    Name: row.name,
                })), ['Model', 'Name']);
            }
            else {
                tui.info(`Found ${rows.length} AI Gateway model(s):`);
                tui.table(rows.map((row) => ({
                    Provider: row.provider,
                    Model: row.id,
                    Name: row.name,
                    API: row.api ?? '-',
                    Reasoning: row.reasoning ? 'yes' : 'no',
                    Context: row.contextWindow ?? '-',
                })), ['Provider', 'Model', 'Name', 'API', 'Reasoning', 'Context']);
            }
        }
        return { models: rows, count: rows.length, model: selectedModel };
    },
});
//# sourceMappingURL=models.js.map