import { s as normalizeOptionalString } from "./string-coerce-CIT1-v_a.js";
import { n as resolvePreferredKaijiBotTmpDir } from "./tmp-kaijibot-dir-NjkPBIBe.js";
import { t as asFiniteNumber } from "./number-coercion-hI-WD8hi.js";
import "./temp-path-DeEO70to.js";
import { i as isVoiceCompatibleAudio } from "./audio-DgO36gjT.js";
import "./media-runtime-CEvKzgJA.js";
import { n as asObject, t as asBoolean } from "./provider-error-utils-KbVjBW-F.js";
import "./speech-DwtHsNyO.js";
import { n as inferEdgeExtension, t as edgeTTS } from "./tts-DMjoxXxJ.js";
import { mkdirSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
import path from "node:path";
import { CHROMIUM_FULL_VERSION, TRUSTED_CLIENT_TOKEN, generateSecMsGecToken } from "node-edge-tts/dist/drm.js";
//#region extensions/microsoft/speech-provider.ts
const DEFAULT_EDGE_VOICE = "en-US-MichelleNeural";
const DEFAULT_EDGE_LANG = "en-US";
const DEFAULT_EDGE_OUTPUT_FORMAT = "audio-24khz-48kbitrate-mono-mp3";
function normalizeMicrosoftProviderConfig(rawConfig) {
	const providers = asObject(rawConfig.providers);
	const rawEdge = asObject(rawConfig.edge);
	const rawMicrosoft = asObject(rawConfig.microsoft);
	const rawProvider = asObject(providers?.microsoft);
	const raw = {
		...rawEdge,
		...rawMicrosoft,
		...rawProvider
	};
	const outputFormat = normalizeOptionalString(raw.outputFormat);
	return {
		enabled: asBoolean(raw.enabled) ?? true,
		voice: normalizeOptionalString(raw.voice) ?? DEFAULT_EDGE_VOICE,
		lang: normalizeOptionalString(raw.lang) ?? DEFAULT_EDGE_LANG,
		outputFormat: outputFormat ?? DEFAULT_EDGE_OUTPUT_FORMAT,
		outputFormatConfigured: Boolean(outputFormat),
		pitch: normalizeOptionalString(raw.pitch),
		rate: normalizeOptionalString(raw.rate),
		volume: normalizeOptionalString(raw.volume),
		saveSubtitles: asBoolean(raw.saveSubtitles) ?? false,
		proxy: normalizeOptionalString(raw.proxy),
		timeoutMs: asFiniteNumber(raw.timeoutMs)
	};
}
function readMicrosoftProviderConfig(config) {
	const defaults = normalizeMicrosoftProviderConfig({});
	return {
		enabled: asBoolean(config.enabled) ?? defaults.enabled,
		voice: normalizeOptionalString(config.voice) ?? defaults.voice,
		lang: normalizeOptionalString(config.lang) ?? defaults.lang,
		outputFormat: normalizeOptionalString(config.outputFormat) ?? defaults.outputFormat,
		outputFormatConfigured: asBoolean(config.outputFormatConfigured) ?? defaults.outputFormatConfigured,
		pitch: normalizeOptionalString(config.pitch) ?? defaults.pitch,
		rate: normalizeOptionalString(config.rate) ?? defaults.rate,
		volume: normalizeOptionalString(config.volume) ?? defaults.volume,
		saveSubtitles: asBoolean(config.saveSubtitles) ?? defaults.saveSubtitles,
		proxy: normalizeOptionalString(config.proxy) ?? defaults.proxy,
		timeoutMs: asFiniteNumber(config.timeoutMs) ?? defaults.timeoutMs
	};
}
function buildMicrosoftVoiceHeaders() {
	const major = CHROMIUM_FULL_VERSION.split(".")[0] || "0";
	return {
		Authority: "speech.platform.bing.com",
		Origin: "chrome-extension://jdiccldimpdaibmpdkjnbmckianbfold",
		Accept: "*/*",
		"User-Agent": `Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/${major}.0.0.0 Safari/537.36 Edg/${major}.0.0.0`,
		"Sec-MS-GEC": generateSecMsGecToken(),
		"Sec-MS-GEC-Version": `1-${CHROMIUM_FULL_VERSION}`
	};
}
function formatMicrosoftVoiceDescription(entry) {
	const personalities = entry.VoiceTag?.VoicePersonalities?.filter(Boolean) ?? [];
	return personalities.length > 0 ? personalities.join(", ") : void 0;
}
function isCjkDominant(text) {
	const stripped = text.replace(/\s+/g, "");
	if (stripped.length === 0) return false;
	let cjkCount = 0;
	for (const ch of stripped) {
		const code = ch.codePointAt(0) ?? 0;
		if (code >= 19968 && code <= 40959 || code >= 13312 && code <= 19903 || code >= 12288 && code <= 12351 || code >= 65280 && code <= 65519) cjkCount += 1;
	}
	return cjkCount / stripped.length > .3;
}
const DEFAULT_CHINESE_EDGE_VOICE = "zh-CN-XiaoxiaoNeural";
const DEFAULT_CHINESE_EDGE_LANG = "zh-CN";
async function listMicrosoftVoices() {
	const response = await fetch(`https://speech.platform.bing.com/consumer/speech/synthesize/readaloud/voices/list?trustedclienttoken=${TRUSTED_CLIENT_TOKEN}`, { headers: buildMicrosoftVoiceHeaders() });
	if (!response.ok) throw new Error(`Microsoft voices API error (${response.status})`);
	const voices = await response.json();
	return Array.isArray(voices) ? voices.map((voice) => ({
		id: voice.ShortName?.trim() ?? "",
		name: normalizeOptionalString(voice.FriendlyName) ?? normalizeOptionalString(voice.ShortName),
		category: voice.VoiceTag?.ContentCategories?.find((value) => value.trim().length > 0),
		description: formatMicrosoftVoiceDescription(voice),
		locale: normalizeOptionalString(voice.Locale),
		gender: normalizeOptionalString(voice.Gender),
		personalities: voice.VoiceTag?.VoicePersonalities?.filter((value) => value.trim().length > 0)
	})).filter((voice) => voice.id.length > 0) : [];
}
function buildMicrosoftSpeechProvider() {
	return {
		id: "microsoft",
		label: "Microsoft",
		aliases: ["edge"],
		autoSelectOrder: 30,
		resolveConfig: ({ rawConfig }) => normalizeMicrosoftProviderConfig(rawConfig),
		resolveTalkConfig: ({ baseTtsConfig, talkProviderConfig }) => {
			return {
				...normalizeMicrosoftProviderConfig(baseTtsConfig),
				enabled: true,
				...normalizeOptionalString(talkProviderConfig.voiceId) == null ? {} : { voice: normalizeOptionalString(talkProviderConfig.voiceId) },
				...normalizeOptionalString(talkProviderConfig.languageCode) == null ? {} : { lang: normalizeOptionalString(talkProviderConfig.languageCode) },
				...normalizeOptionalString(talkProviderConfig.outputFormat) == null ? {} : { outputFormat: normalizeOptionalString(talkProviderConfig.outputFormat) },
				...normalizeOptionalString(talkProviderConfig.pitch) == null ? {} : { pitch: normalizeOptionalString(talkProviderConfig.pitch) },
				...normalizeOptionalString(talkProviderConfig.rate) == null ? {} : { rate: normalizeOptionalString(talkProviderConfig.rate) },
				...normalizeOptionalString(talkProviderConfig.volume) == null ? {} : { volume: normalizeOptionalString(talkProviderConfig.volume) },
				...normalizeOptionalString(talkProviderConfig.proxy) == null ? {} : { proxy: normalizeOptionalString(talkProviderConfig.proxy) },
				...asFiniteNumber(talkProviderConfig.timeoutMs) == null ? {} : { timeoutMs: asFiniteNumber(talkProviderConfig.timeoutMs) }
			};
		},
		resolveTalkOverrides: ({ params }) => ({
			...normalizeOptionalString(params.voiceId) == null ? {} : { voice: normalizeOptionalString(params.voiceId) },
			...normalizeOptionalString(params.outputFormat) == null ? {} : { outputFormat: normalizeOptionalString(params.outputFormat) }
		}),
		listVoices: async () => await listMicrosoftVoices(),
		isConfigured: ({ providerConfig }) => readMicrosoftProviderConfig(providerConfig).enabled,
		synthesize: async (req) => {
			const config = readMicrosoftProviderConfig(req.providerConfig);
			const tempRoot = resolvePreferredKaijiBotTmpDir();
			mkdirSync(tempRoot, {
				recursive: true,
				mode: 448
			});
			const tempDir = mkdtempSync(path.join(tempRoot, "tts-microsoft-"));
			const overrideVoice = normalizeOptionalString(req.providerOverrides?.voice);
			let voice = overrideVoice ?? config.voice;
			let lang = config.lang;
			let outputFormat = normalizeOptionalString(req.providerOverrides?.outputFormat) ?? config.outputFormat;
			const fallbackOutputFormat = outputFormat !== DEFAULT_EDGE_OUTPUT_FORMAT ? DEFAULT_EDGE_OUTPUT_FORMAT : void 0;
			if (!overrideVoice && voice === DEFAULT_EDGE_VOICE && isCjkDominant(req.text)) {
				voice = DEFAULT_CHINESE_EDGE_VOICE;
				lang = DEFAULT_CHINESE_EDGE_LANG;
			}
			try {
				const runEdge = async (format) => {
					const fileExtension = inferEdgeExtension(format);
					const outputPath = path.join(tempDir, `speech${fileExtension}`);
					await edgeTTS({
						text: req.text,
						outputPath,
						config: {
							...config,
							voice,
							lang,
							outputFormat: format
						},
						timeoutMs: req.timeoutMs
					});
					return {
						audioBuffer: readFileSync(outputPath),
						outputFormat: format,
						fileExtension,
						voiceCompatible: isVoiceCompatibleAudio({ fileName: outputPath })
					};
				};
				try {
					return await runEdge(outputFormat);
				} catch (error) {
					if (!fallbackOutputFormat || fallbackOutputFormat === outputFormat) throw error;
					outputFormat = fallbackOutputFormat;
					return await runEdge(outputFormat);
				}
			} finally {
				rmSync(tempDir, {
					recursive: true,
					force: true
				});
			}
		}
	};
}
//#endregion
export { isCjkDominant as n, listMicrosoftVoices as r, buildMicrosoftSpeechProvider as t };
