import { isYouTubeUrl } from "../../url.js";
import { resolveTranscriptionConfig } from "../transcription-config.js";
import { resolveTranscriptProviderCapabilities } from "./transcription-capability.js";
import { tryNativeYoutubeMediaTranscript } from "./youtube/native-media.js";
import { buildUnavailableResult, loadYoutubeHtml, resolveDurationMetadata, resolveEffectiveVideoId, tryApifyTranscript, tryManualCaptionTranscript, tryWebTranscript, tryYtDlpTranscript, } from "./youtube/provider-flow.js";
export const canHandle = ({ url }) => isYouTubeUrl(url);
export const fetchTranscript = async (context, options) => {
    const attemptedProviders = [];
    const notes = [];
    const transcription = resolveTranscriptionConfig(options);
    const { url } = context;
    const html = await loadYoutubeHtml(context, options);
    const mode = options.youtubeTranscriptMode;
    const diarization = options.transcriptDiarization ?? null;
    const progress = typeof options.onProgress === "function" ? options.onProgress : null;
    const transcriptionCapabilities = await resolveTranscriptProviderCapabilities({
        transcription,
        ytDlpPath: options.ytDlpPath,
        diarization,
    });
    const canRunYtDlp = transcriptionCapabilities.canRunYtDlp;
    const canTranscribe = transcriptionCapabilities.canTranscribe;
    const pushHint = (hint) => {
        progress?.({ kind: "transcript-start", url, service: "youtube", hint });
    };
    if (mode === "yt-dlp" && !options.ytDlpPath) {
        throw new Error("Missing yt-dlp binary for --youtube yt-dlp (set YT_DLP_PATH or install yt-dlp)");
    }
    if (mode === "yt-dlp" && !transcriptionCapabilities.canTranscribe) {
        throw new Error("Missing transcription provider for --youtube yt-dlp (install whisper-cpp or set GROQ_API_KEY/ASSEMBLYAI_API_KEY/GEMINI_API_KEY/OPENAI_API_KEY/FAL_KEY/DEEPGRAM_API_KEY)");
    }
    if (diarization && !options.ytDlpPath) {
        throw new Error("Speaker diarization for YouTube requires yt-dlp (set YT_DLP_PATH or install yt-dlp)");
    }
    if (diarization && !transcriptionCapabilities.canTranscribe) {
        throw new Error(transcriptionCapabilities.missingProviderNote);
    }
    const effectiveVideoId = resolveEffectiveVideoId(context);
    const canProceedWithoutWebContext = mode === "apify" ||
        (mode === "auto" && Boolean(options.apifyApiToken)) ||
        (canRunYtDlp &&
            (Boolean(diarization) || mode === "yt-dlp" || mode === "no-auto" || mode === "auto"));
    // yt-dlp and Apify fallbacks can run from the URL alone; web caption providers cannot.
    if (!html && !canProceedWithoutWebContext) {
        return { text: null, source: null, attemptedProviders };
    }
    const htmlText = html ?? "";
    if (!effectiveVideoId && !canProceedWithoutWebContext) {
        return { text: null, source: null, attemptedProviders };
    }
    const durationMetadata = await resolveDurationMetadata({
        htmlText,
        effectiveVideoId,
        url,
        options,
    });
    const flow = {
        context,
        options,
        transcription,
        htmlText,
        attemptedProviders,
        notes,
        effectiveVideoId,
        durationMetadata,
        canTranscribe,
        canRunYtDlp,
        pushHint,
    };
    if (diarization) {
        const transcript = await tryYtDlpTranscript({ flow, mode: "yt-dlp" });
        if (transcript)
            return transcript;
        throw new Error("Speaker diarization returned no transcript");
    }
    // Try no-auto mode (skip auto-generated captions, fall back to yt-dlp)
    if (mode === "no-auto") {
        const manualTranscript = await tryManualCaptionTranscript(flow);
        if (manualTranscript)
            return manualTranscript;
        notes.push("No creator captions found, using audio transcription");
    }
    // Try web methods (youtubei, captionTracks) if mode is 'auto' or 'web'
    if (mode === "auto" || mode === "web") {
        const transcript = await tryWebTranscript(flow);
        if (transcript)
            return transcript;
    }
    // Try yt-dlp (audio download + cloud/local transcription) if mode is 'auto', 'no-auto', or 'yt-dlp'
    if (mode === "yt-dlp" || ((mode === "no-auto" || mode === "auto") && canRunYtDlp)) {
        const transcript = await tryYtDlpTranscript({ flow, mode });
        if (transcript)
            return transcript;
    }
    if ((mode === "auto" || mode === "no-auto") && canTranscribe) {
        const nativeResult = await tryNativeYoutubeMediaTranscript(flow);
        if (nativeResult)
            return nativeResult;
    }
    // Auto mode: only try Apify after local audio fallbacks fail (last resort).
    if (mode === "auto") {
        const apifyResult = await tryApifyTranscript(flow, canRunYtDlp
            ? "YouTube: audio transcription failed; trying Apify"
            : "YouTube: captions unavailable; trying Apify");
        if (apifyResult)
            return apifyResult;
    }
    // Explicit apify mode: allow forcing it, but require a token.
    if (mode === "apify") {
        if (!options.apifyApiToken) {
            throw new Error("Missing APIFY_API_TOKEN for --youtube apify");
        }
        const apifyResult = await tryApifyTranscript(flow, "YouTube: fetching transcript (Apify)");
        if (apifyResult)
            return apifyResult;
    }
    return buildUnavailableResult(flow);
};
//# sourceMappingURL=youtube.js.map