import { withBunCompressionHeaders } from "../../../bun.js";
import { fetchWithTimeout } from "../../../link-preview/fetch-with-timeout.js";
import { rankYoutubeCaptionTracks, resolveYoutubeCaptionTrack, } from "../../../youtube-captions.js";
import { sanitizeYoutubeJsonResponse } from "../../utils.js";
import { extractYoutubeiBootstrap } from "./api.js";
import { extractInitialPlayerResponse, extractInnertubeApiKey } from "./captions-player.js";
import { REQUEST_HEADERS, isObjectLike, } from "./captions-shared.js";
async function fetchTranscriptViaAndroidPlayer(fetchImpl, { html, videoId, skipAutoGenerated, }) {
    const apiKey = extractInnertubeApiKey(html);
    if (!apiKey) {
        return null;
    }
    try {
        const userAgent = REQUEST_HEADERS["User-Agent"] ??
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36";
        const response = await fetchWithTimeout(fetchImpl, `https://www.youtube.com/youtubei/v1/player?key=${apiKey}`, {
            method: "POST",
            headers: withBunCompressionHeaders({
                "Content-Type": "application/json",
                "User-Agent": userAgent,
                "Accept-Language": REQUEST_HEADERS["Accept-Language"] ?? "en-US,en;q=0.9",
                Accept: "application/json",
            }),
            body: JSON.stringify({
                context: {
                    client: {
                        clientName: "ANDROID",
                        clientVersion: "20.10.38",
                    },
                },
                videoId,
            }),
        });
        if (!response.ok) {
            return null;
        }
        const parsed = await response.json();
        if (!isObjectLike(parsed)) {
            return null;
        }
        return await extractTranscriptFromPlayerPayload(fetchImpl, parsed, skipAutoGenerated);
    }
    catch {
        return null;
    }
}
export const fetchTranscriptFromCaptionTracks = async (fetchImpl, { html, originalUrl, videoId, skipAutoGenerated, }) => {
    const initialPlayerResponse = extractInitialPlayerResponse(html);
    if (initialPlayerResponse) {
        const transcript = await extractTranscriptFromPlayerPayload(fetchImpl, initialPlayerResponse, skipAutoGenerated);
        if (transcript) {
            return transcript;
        }
    }
    const bootstrap = extractYoutubeiBootstrap(html);
    if (!bootstrap) {
        return await fetchTranscriptViaAndroidPlayer(fetchImpl, { html, videoId, skipAutoGenerated });
    }
    const { apiKey, clientName, clientVersion, context, pageCl, pageLabel, visitorData, xsrfToken } = bootstrap;
    if (!apiKey) {
        return await fetchTranscriptViaAndroidPlayer(fetchImpl, { html, videoId, skipAutoGenerated });
    }
    const contextRecord = context;
    const clientContext = isObjectLike(contextRecord.client)
        ? contextRecord.client
        : {};
    const requestBody = {
        context: {
            ...contextRecord,
            client: {
                ...clientContext,
                originalUrl,
            },
        },
        videoId,
        playbackContext: {
            contentPlaybackContext: {
                html5Preference: "HTML5_PREF_WANTS",
            },
        },
        contentCheckOk: true,
        racyCheckOk: true,
    };
    try {
        const userAgent = REQUEST_HEADERS["User-Agent"] ??
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36";
        const headers = withBunCompressionHeaders({
            "Content-Type": "application/json",
            "User-Agent": userAgent,
            Accept: "application/json",
            Origin: "https://www.youtube.com",
            Referer: originalUrl,
            "X-Goog-AuthUser": "0",
            "X-Youtube-Bootstrap-Logged-In": "false",
        });
        if (clientName)
            headers["X-Youtube-Client-Name"] = clientName;
        if (clientVersion)
            headers["X-Youtube-Client-Version"] = clientVersion;
        if (visitorData)
            headers["X-Goog-Visitor-Id"] = visitorData;
        if (typeof pageCl === "number" && Number.isFinite(pageCl)) {
            headers["X-Youtube-Page-CL"] = String(pageCl);
        }
        if (pageLabel)
            headers["X-Youtube-Page-Label"] = pageLabel;
        if (xsrfToken)
            headers["X-Youtube-Identity-Token"] = xsrfToken;
        const response = await fetchWithTimeout(fetchImpl, `https://www.youtube.com/youtubei/v1/player?key=${apiKey}`, {
            method: "POST",
            headers,
            body: JSON.stringify(requestBody),
        });
        if (!response.ok) {
            return await fetchTranscriptViaAndroidPlayer(fetchImpl, { html, videoId, skipAutoGenerated });
        }
        const raw = await response.text();
        const sanitized = sanitizeYoutubeJsonResponse(raw);
        const parsed = JSON.parse(sanitized);
        if (!isObjectLike(parsed)) {
            return await fetchTranscriptViaAndroidPlayer(fetchImpl, { html, videoId, skipAutoGenerated });
        }
        const transcript = await extractTranscriptFromPlayerPayload(fetchImpl, parsed, skipAutoGenerated);
        if (transcript) {
            return transcript;
        }
        return await fetchTranscriptViaAndroidPlayer(fetchImpl, { html, videoId, skipAutoGenerated });
    }
    catch {
        return await fetchTranscriptViaAndroidPlayer(fetchImpl, { html, videoId, skipAutoGenerated });
    }
};
const extractTranscriptFromPlayerPayload = async (fetchImpl, payload, skipAutoGenerated) => {
    const payloadRecord = payload;
    const captionsCandidate = payloadRecord.captions;
    const captions = isObjectLike(captionsCandidate) ? captionsCandidate : null;
    const rendererCandidate = (captions ? captions.playerCaptionsTracklistRenderer : null) ??
        payloadRecord.playerCaptionsTracklistRenderer;
    const renderer = isObjectLike(rendererCandidate)
        ? rendererCandidate
        : null;
    const captionTracks = Array.isArray(renderer?.captionTracks)
        ? renderer?.captionTracks
        : null;
    const automaticTracks = Array.isArray(renderer?.automaticCaptions)
        ? renderer?.automaticCaptions
        : null;
    const tracksToUse = rankYoutubeCaptionTracks({
        captionTracks: captionTracks ?? [],
        automaticCaptionTracks: automaticTracks ?? [],
        skipAutoGenerated,
        priority: "manual-first",
    });
    if (tracksToUse.length === 0) {
        return null;
    }
    return await findFirstTranscript(fetchImpl, tracksToUse, 0);
};
const findFirstTranscript = async (fetchImpl, tracks, index) => {
    if (index >= tracks.length) {
        return null;
    }
    const track = tracks[index];
    if (!track)
        return null;
    const candidate = await downloadCaptionTrack(fetchImpl, track);
    if (candidate) {
        return candidate;
    }
    return findFirstTranscript(fetchImpl, tracks, index + 1);
};
const downloadCaptionTrack = async (fetchImpl, track) => {
    const transcript = await resolveYoutubeCaptionTrack(track.baseUrl, async (url) => {
        const response = await fetchWithTimeout(fetchImpl, url, {
            headers: REQUEST_HEADERS,
        });
        return response.ok ? await response.text() : null;
    });
    return transcript ? { text: transcript.text, segments: transcript.segments } : null;
};
//# sourceMappingURL=captions-transcript.js.map