import { formatBytes, formatBytesPerSecond, formatDurationSecondsSmart, formatElapsedMs, } from "../format.js";
export function createTranscriptProgressState() {
    return {
        phase: "idle",
        service: "generic",
        downloadedBytes: 0,
        totalBytes: null,
        startedAtMs: null,
        whisperProviderHint: "unknown",
        mediaKind: "audio",
        whisperModelId: null,
        whisperProcessedSeconds: null,
        whisperTotalSeconds: null,
        whisperPartIndex: null,
        whisperParts: null,
    };
}
export function applyTranscriptProgressEvent(state, event, nowMs) {
    if (event.kind === "transcript-media-download-start") {
        state.phase = "download";
        state.service = event.service;
        state.mediaKind = event.mediaKind ?? state.mediaKind;
        state.downloadedBytes = 0;
        state.totalBytes = event.totalBytes;
        state.startedAtMs = nowMs;
        return;
    }
    if (event.kind === "transcript-media-download-progress") {
        const enteringPhase = state.phase !== "download";
        state.phase = "download";
        state.service = event.service;
        state.mediaKind = event.mediaKind ?? state.mediaKind;
        state.downloadedBytes = event.downloadedBytes;
        state.totalBytes = event.totalBytes;
        if (enteringPhase || state.startedAtMs == null)
            state.startedAtMs = nowMs;
        return;
    }
    if (event.kind === "transcript-media-download-done") {
        const enteringPhase = state.phase !== "download";
        state.phase = "download";
        state.service = event.service;
        state.mediaKind = event.mediaKind ?? state.mediaKind;
        state.downloadedBytes = event.downloadedBytes;
        state.totalBytes = event.totalBytes;
        if (enteringPhase || state.startedAtMs == null)
            state.startedAtMs = nowMs;
        return;
    }
    if (event.kind === "transcript-whisper-start") {
        state.phase = "whisper";
        state.service = event.service;
        state.whisperProviderHint = event.providerHint;
        state.whisperModelId = event.modelId;
        state.whisperProcessedSeconds = null;
        state.whisperTotalSeconds = event.totalDurationSeconds;
        state.whisperPartIndex = 0;
        state.whisperParts = event.parts;
        state.startedAtMs = nowMs;
        return;
    }
    if (event.kind === "transcript-whisper-progress") {
        const enteringPhase = state.phase !== "whisper";
        state.phase = "whisper";
        state.service = event.service;
        state.whisperProcessedSeconds = event.processedDurationSeconds;
        state.whisperTotalSeconds = event.totalDurationSeconds;
        state.whisperPartIndex = event.partIndex;
        state.whisperParts = event.parts;
        if (enteringPhase || state.startedAtMs == null)
            state.startedAtMs = nowMs;
    }
}
export function renderTranscriptSimple(state, theme) {
    if (state.phase === "download")
        return renderSimple(downloadTitle(state), theme);
    if (state.phase === "whisper")
        return renderSimple("Transcribing", theme);
    return null;
}
export function renderTranscriptLine(state, { nowMs, theme, }) {
    if (state.phase === "download")
        return renderDownloadLine(state, nowMs, theme);
    if (state.phase === "whisper")
        return renderWhisperLine(state, nowMs, theme);
    return null;
}
export function resolveTranscriptOscPayload(state) {
    if (state.phase === "download") {
        return { label: downloadTitle(state), percent: resolveDownloadPercent(state) };
    }
    if (state.phase === "whisper") {
        return { label: "Transcribing", percent: resolveWhisperPercent(state) };
    }
    return null;
}
function renderDownloadLine(state, nowMs, theme) {
    const downloaded = formatBytes(state.downloadedBytes);
    const total = typeof state.totalBytes === "number" &&
        state.totalBytes > 0 &&
        state.downloadedBytes <= state.totalBytes
        ? `/${formatBytes(state.totalBytes)}`
        : "";
    const elapsedMs = typeof state.startedAtMs === "number" ? nowMs - state.startedAtMs : 0;
    const elapsed = formatElapsedMs(elapsedMs);
    const rate = elapsedMs > 0 && state.downloadedBytes > 0
        ? `, ${formatBytesPerSecond(state.downloadedBytes / (elapsedMs / 1000))}`
        : "";
    const svcLabel = state.service === "podcast" ? "podcast" : state.service === "youtube" ? "youtube" : "";
    return renderLine(`Downloading ${state.mediaKind === "video" ? "video" : "audio"}`, ` (${svcLabel ? `${svcLabel}, ` : ""}${downloaded}${total}, ${elapsed}${rate})…`, null, theme);
}
function renderWhisperLine(state, nowMs, theme) {
    const provider = formatProvider(firstChainPart(state.whisperProviderHint));
    const modelId = firstChainPart(state.whisperModelId);
    const providerLabel = modelId ? `${provider}, ${modelId}` : provider;
    const svc = state.service === "podcast" ? "podcast" : state.service === "youtube" ? "youtube" : "media";
    const elapsedMs = typeof state.startedAtMs === "number" ? nowMs - state.startedAtMs : 0;
    const elapsed = formatElapsedMs(elapsedMs);
    const percent = typeof state.whisperProcessedSeconds === "number" &&
        typeof state.whisperTotalSeconds === "number" &&
        state.whisperTotalSeconds > 0
        ? Math.min(100, Math.max(0, Math.round((state.whisperProcessedSeconds / state.whisperTotalSeconds) * 100)))
        : null;
    const duration = typeof state.whisperProcessedSeconds === "number" &&
        typeof state.whisperTotalSeconds === "number" &&
        state.whisperTotalSeconds > 0
        ? `, ${formatDurationSecondsSmart(state.whisperProcessedSeconds)}/${formatDurationSecondsSmart(state.whisperTotalSeconds)}`
        : typeof state.whisperTotalSeconds === "number" && state.whisperTotalSeconds > 0
            ? `, ${formatDurationSecondsSmart(state.whisperTotalSeconds)}`
            : "";
    const parts = typeof state.whisperPartIndex === "number" &&
        typeof state.whisperParts === "number" &&
        state.whisperPartIndex > 0 &&
        state.whisperParts > 0
        ? `, ${state.whisperPartIndex}/${state.whisperParts}`
        : "";
    return renderLine("Transcribing", ` (${svc}, ${providerLabel}${duration}${parts}, ${elapsed})…`, typeof percent === "number" ? `${percent}%` : null, theme);
}
function renderLine(label, detail, percentLabel, theme) {
    if (!theme)
        return `${label}${percentLabel ? ` ${percentLabel}` : ""}${detail}`;
    const percent = percentLabel ? ` ${theme.value(percentLabel)}` : "";
    return `${theme.label(label)}${percent}${theme.dim(detail)}`;
}
function renderSimple(label, theme) {
    return theme ? `${theme.label(label)}${theme.dim("…")}` : `${label}…`;
}
function downloadTitle(state) {
    return state.mediaKind === "video" ? "Downloading video" : "Downloading audio";
}
function resolveDownloadPercent(state) {
    if (typeof state.totalBytes !== "number" || state.totalBytes <= 0)
        return null;
    if (state.downloadedBytes <= 0)
        return 0;
    return (state.downloadedBytes / state.totalBytes) * 100;
}
function resolveWhisperPercent(state) {
    if (typeof state.whisperTotalSeconds === "number" && state.whisperTotalSeconds > 0) {
        const processed = typeof state.whisperProcessedSeconds === "number" ? state.whisperProcessedSeconds : 0;
        return (processed / state.whisperTotalSeconds) * 100;
    }
    if (typeof state.whisperParts === "number" && state.whisperParts > 0) {
        const index = typeof state.whisperPartIndex === "number" ? state.whisperPartIndex : 0;
        return (index / state.whisperParts) * 100;
    }
    return null;
}
function formatProvider(hint) {
    if (hint === "cpp")
        return "Whisper.cpp";
    if (hint === "onnx")
        return "ONNX (Parakeet/Canary)";
    const labelForPart = (part, chained) => {
        if (part === "groq")
            return "Whisper/Groq";
        if (part === "assemblyai")
            return "AssemblyAI";
        if (part === "gemini")
            return "Gemini";
        if (part === "openai")
            return "Whisper/OpenAI";
        if (part === "fal")
            return chained ? "FAL" : "Whisper/FAL";
        return part;
    };
    if (hint === "groq")
        return "Whisper/Groq";
    if (hint === "assemblyai")
        return "AssemblyAI";
    if (hint === "gemini")
        return "Gemini";
    if (hint === "openai")
        return "Whisper/OpenAI";
    if (hint === "fal")
        return "Whisper/FAL";
    return "Whisper";
}
function firstChainPart(value) {
    return value?.split("->", 1)[0]?.trim() || null;
}
//# sourceMappingURL=transcript-state.js.map