import { REASONING_BUDGET_MAP } from './interface.js';
import { mapAnthropicStopReason } from './stop-reason-maps.js';
import { fromAnthropicContent, parseToolCallArguments, toAnthropicMessages, toAnthropicTools, } from './tool-formats.js';
import { ProviderError } from '../types/errors.js';
import { withRetry } from '../utils/retry.js';
import { buildStandardProviderAuthRoutes } from './runtime-metadata.js';
import { toProviderError } from '../utils/error-display.js';
const DEFAULT_MAX_OUTPUT = 8192;
function normalizeAnthropicModel(model) {
    if (model.startsWith('anthropic:'))
        return model.slice('anthropic:'.length);
    if (model.startsWith('anthropic/'))
        return model.slice('anthropic/'.length);
    return model;
}
export class AnthropicSdkProvider {
    options;
    name;
    models;
    constructor(options) {
        this.options = options;
        this.name = options.name;
        this.models = [...options.models];
    }
    async chat(params) {
        return withRetry(async () => {
            const client = this.options.createClient();
            const resolvedModel = normalizeAnthropicModel(params.model ?? this.options.defaultModel);
            const body = {
                model: resolvedModel,
                max_tokens: params.maxTokens ?? DEFAULT_MAX_OUTPUT,
                messages: toAnthropicMessages(params.messages),
                stream: true,
            };
            if (params.systemPrompt) {
                body['system'] = params.systemPrompt;
            }
            if (params.tools && params.tools.length > 0) {
                body['tools'] = toAnthropicTools(params.tools);
            }
            if (params.reasoningEffort && params.reasoningEffort !== 'instant') {
                const budget = REASONING_BUDGET_MAP[params.reasoningEffort];
                if (typeof budget === 'number' && budget > 0) {
                    body['thinking'] = { type: 'enabled', budget_tokens: budget };
                    const currentMax = body['max_tokens'] ?? DEFAULT_MAX_OUTPUT;
                    if (currentMax <= budget)
                        body['max_tokens'] = budget + 4096;
                }
            }
            const toolBlocks = new Map();
            let responseText = '';
            let rawStopReason;
            let stopReason = 'unknown';
            try {
                const streamFactory = client.messages.stream;
                const stream = streamFactory(body, params.signal ? { signal: params.signal } : undefined);
                for await (const event of stream) {
                    if (event.type === 'content_block_start' && event.content_block.type === 'tool_use') {
                        const idx = event.index ?? 0;
                        toolBlocks.set(idx, {
                            id: event.content_block.id ?? '',
                            name: event.content_block.name ?? '',
                            args: '',
                        });
                        params.onDelta?.({
                            toolCalls: [{ index: idx, id: event.content_block.id, name: event.content_block.name }],
                        });
                    }
                    else if (event.type === 'content_block_delta') {
                        const idx = event.index ?? 0;
                        if (event.delta.type === 'text_delta' && event.delta.text) {
                            responseText += event.delta.text;
                            params.onDelta?.({ content: event.delta.text });
                        }
                        else if (event.delta.type === 'thinking_delta' && event.delta.thinking) {
                            params.onDelta?.({ reasoning: event.delta.thinking });
                        }
                        else if (event.delta.type === 'input_json_delta' && event.delta.partial_json) {
                            const block = toolBlocks.get(idx);
                            if (block)
                                block.args += event.delta.partial_json;
                            params.onDelta?.({
                                toolCalls: [{ index: idx, arguments: event.delta.partial_json }],
                            });
                        }
                    }
                    else if (event.type === 'message_delta') {
                        if (event.delta.stop_reason) {
                            rawStopReason = event.delta.stop_reason;
                            stopReason = mapAnthropicStopReason(rawStopReason);
                        }
                    }
                }
                const finalMessage = await stream.finalMessage();
                const contentBlocks = [];
                if (responseText) {
                    contentBlocks.push({ type: 'text', text: responseText });
                }
                for (const [, block] of [...toolBlocks.entries()].sort(([a], [b]) => a - b)) {
                    const parsedInput = parseToolCallArguments(block.args, {
                        provider: this.name,
                        toolName: block.name,
                        callId: block.id,
                    });
                    if (parsedInput === undefined)
                        continue;
                    contentBlocks.push({
                        type: 'tool_use',
                        id: block.id,
                        name: block.name,
                        input: parsedInput,
                    });
                }
                const parsed = contentBlocks.length > 0
                    ? fromAnthropicContent(contentBlocks)
                    : fromAnthropicContent(finalMessage.content);
                return {
                    content: parsed.text,
                    toolCalls: parsed.toolCalls,
                    usage: {
                        inputTokens: finalMessage.usage.input_tokens,
                        outputTokens: finalMessage.usage.output_tokens,
                        ...(finalMessage.usage.cache_read_input_tokens != null ? { cacheReadTokens: finalMessage.usage.cache_read_input_tokens } : {}),
                        ...(finalMessage.usage.cache_creation_input_tokens != null ? { cacheWriteTokens: finalMessage.usage.cache_creation_input_tokens } : {}),
                    },
                    stopReason: stopReason === 'unknown' && parsed.text ? 'completed' : stopReason,
                    ...(rawStopReason !== undefined ? { providerStopReason: rawStopReason } : {}),
                };
            }
            catch (error) {
                throw toProviderError(error, {
                    provider: this.name,
                    operation: 'chat',
                    phase: 'stream',
                });
            }
        });
    }
    async describeRuntime(deps) {
        const authRoutes = await buildStandardProviderAuthRoutes({
            providerId: this.options.name,
            apiKeyEnvVars: this.options.auth.envVars,
            secretKeys: this.options.auth.secretKeys,
            serviceNames: this.options.auth.serviceNames,
            allowAnonymous: this.options.auth.allowAnonymous,
            anonymousConfigured: this.options.auth.anonymousConfigured,
            anonymousDetail: this.options.auth.anonymousDetail,
        }, deps);
        return {
            auth: {
                mode: this.options.auth.mode,
                configured: this.options.auth.configured,
                detail: this.options.auth.detail,
                ...(this.options.auth.envVars ? { envVars: this.options.auth.envVars } : {}),
                routes: authRoutes,
            },
            models: {
                defaultModel: this.options.defaultModel,
                models: this.models,
            },
            usage: {
                streaming: true,
                toolCalling: true,
                parallelTools: true,
                promptCaching: true,
                ...(this.options.notes ? { notes: this.options.notes } : {}),
            },
            policy: {
                local: false,
                streamProtocol: this.options.streamProtocol,
                reasoningMode: 'thinking_budget',
                supportedReasoningEfforts: ['instant', 'low', 'medium', 'high'],
            },
        };
    }
}
