import { openAsBlob } from "node:fs";
import { MAX_ERROR_DETAIL_CHARS, TRANSCRIPTION_TIMEOUT_MS } from "./constants.js";
import { resolveDeepgramTranscriptionModel } from "./provider-setup.js";
import { toArrayBuffer } from "./utils.js";
const DEEPGRAM_BASE_URL = "https://api.deepgram.com/v1";
export async function transcribeWithDeepgram(bytes, mediaType, apiKey, options = {}) {
    return await transcribeDeepgramBody(new Blob([toArrayBuffer(bytes)], { type: normalizeMediaType(mediaType) }), mediaType, apiKey, options);
}
export async function transcribeFileWithDeepgram({ filePath, mediaType, apiKey, ...options }) {
    return await transcribeDeepgramBody(await openAsBlob(filePath, { type: normalizeMediaType(mediaType) }), mediaType, apiKey, options);
}
async function transcribeDeepgramBody(body, mediaType, apiKey, { fetchImpl = globalThis.fetch, baseUrl = DEEPGRAM_BASE_URL, env, model, timeoutMs = TRANSCRIPTION_TIMEOUT_MS, }) {
    const url = new URL(`${baseUrl.replace(/\/+$/, "")}/listen`);
    url.searchParams.set("model", model?.trim() || resolveDeepgramTranscriptionModel(env));
    url.searchParams.set("smart_format", "true");
    url.searchParams.set("detect_language", "true");
    url.searchParams.set("utterances", "true");
    const response = await fetchImpl(url, {
        method: "POST",
        headers: {
            authorization: `Token ${apiKey}`,
            "content-type": normalizeMediaType(mediaType),
        },
        body,
        signal: AbortSignal.timeout(timeoutMs),
        duplex: "half",
    });
    if (!response.ok) {
        const detail = await readErrorDetail(response);
        throw new Error(`Deepgram transcription failed (${response.status})${detail ? `: ${detail}` : ""}`);
    }
    const payload = await response.json().catch(() => null);
    return parseDeepgramResponse(payload);
}
export function parseDeepgramResponse(payload) {
    if (!payload || typeof payload !== "object")
        return { text: null, segments: null };
    const results = payload.results;
    if (!results || typeof results !== "object")
        return { text: null, segments: null };
    const channels = results.channels;
    const firstChannel = Array.isArray(channels) ? channels[0] : null;
    const alternatives = firstChannel && typeof firstChannel === "object"
        ? firstChannel.alternatives
        : null;
    const firstAlternative = Array.isArray(alternatives) ? alternatives[0] : null;
    const rawTranscript = firstAlternative && typeof firstAlternative === "object"
        ? firstAlternative.transcript
        : null;
    const text = typeof rawTranscript === "string" ? rawTranscript.trim() || null : null;
    const utterances = results.utterances;
    const segments = Array.isArray(utterances)
        ? utterances
            .map(parseDeepgramUtterance)
            .filter((segment) => segment !== null)
        : [];
    return { text, segments: segments.length > 0 ? segments : null };
}
function parseDeepgramUtterance(value) {
    if (!value || typeof value !== "object")
        return null;
    const utterance = value;
    const text = typeof utterance.transcript === "string"
        ? utterance.transcript.replace(/\s+/g, " ").trim()
        : "";
    const startMs = secondsToMs(utterance.start);
    const endMs = secondsToMs(utterance.end);
    if (!text || startMs == null)
        return null;
    return { startMs, endMs, text };
}
function secondsToMs(value) {
    return typeof value === "number" && Number.isFinite(value) && value >= 0
        ? Math.round(value * 1000)
        : null;
}
function normalizeMediaType(value) {
    return value.trim() || "application/octet-stream";
}
async function readErrorDetail(response) {
    try {
        const text = (await response.text()).trim();
        if (!text)
            return null;
        return text.length > MAX_ERROR_DETAIL_CHARS
            ? `${text.slice(0, MAX_ERROR_DETAIL_CHARS)}…`
            : text;
    }
    catch {
        return null;
    }
}
//# sourceMappingURL=deepgram.js.map