import { mylog } from "./utilities";

const GOOGLE_API_KEY = 'AIzaSyDgjlam13lZhUudC9QnCmO5pkSiuBIDkxA'; 
let isSpeaking = false;
let currentAudio = null;

/**
 * Hilfsfunktion: Lädt einen Text-Chunk von Google vor (ohne ihn abzuspielen).
 */
async function prepareGoogleAudio(text) {
    if (!text || text.trim().length === 0) return null;
    
    const url = `https://texttospeech.googleapis.com/v1/text:synthesize?key=${GOOGLE_API_KEY}`;
    const response = await fetch(url, {
        method: 'POST',
        body: JSON.stringify({
            input: { text },
            voice: { languageCode: 'de-DE', name: 'de-DE-Neural2-F', ssmlGender: 'FEMALE' },
            audioConfig: { audioEncoding: 'MP3', speakingRate: 0.95 }
        })
    });

    if (!response.ok) throw new Error("Google API Fehler");
    const data = await response.json();
    return new Audio(`data:audio/mp3;base64,${data.audioContent}`);
}

/**
 * Kern-Logik: Spielt Text mit Preloading ab.
 */
async function speakWithPreloading(text) {
    // 1. Text in Sätze zerlegen
    const sentences = text.split(/(?<=[.?!;])\s*/).filter(s => s.trim().length > 0);
    if (sentences.length === 0) return;

    // 2. Chunks bilden: Erster Chunk klein (2 Sätze), Rest moderat (4 Sätze)
    let chunks = [];
    chunks.push(sentences.slice(0, 2).join(' ')); // Schnellstart
    
    for (let i = 2; i < sentences.length; i += 4) {
        chunks.push(sentences.slice(i, i + 4).join(' '));
    }

    let nextAudioPromise = null;

    for (let i = 0; i < chunks.length; i++) {
        if (!isSpeaking) break;

        // Entweder wir nehmen das vorbereitete Audio oder laden es jetzt (beim ersten Chunk)
        let audio;
        try {
            audio = nextAudioPromise ? await nextAudioPromise : await prepareGoogleAudio(chunks[i]);
        } catch (e) {
            throw new Error("Fehler beim Laden des Google Audios");
        }

        if (!isSpeaking) break;
        currentAudio = audio;

        // SOFORT den NÄCHSTEN Chunk im Hintergrund laden
        if (i + 1 < chunks.length) {
            nextAudioPromise = prepareGoogleAudio(chunks[i + 1]);
        }

        // Aktuellen Chunk abspielen
        await new Promise((resolve, reject) => {
            currentAudio.onended = resolve;
            currentAudio.onerror = reject;
            currentAudio.play().catch(reject);
        });
    }
}

/**
 * Browser-Fallback (Deine bewährte Methode)
 */
async function speakChunksFallback(text) {
    const sentences = text.split(/(?<=[.?!;])\s*/);
    for (const sentence of sentences) {
        if (!isSpeaking) break;
        await new Promise(resolve => {
            const utterance = new SpeechSynthesisUtterance(sentence.trim());
            utterance.lang = 'de-DE';
            utterance.onend = resolve;
            utterance.onerror = resolve;
            window.speechSynthesis.speak(utterance);
        });
    }
}

export function cancelSpeech() {
    isSpeaking = false;
    if (currentAudio) {
        currentAudio.pause();
        currentAudio.src = "";
        currentAudio = null;
    }
    window.speechSynthesis.cancel();
}

async function getBiographyText(url) {
    const response = await fetch(url);
    const htmlText = await response.text();
    const parser = new DOMParser();
    const doc = parser.parseFromString(htmlText, 'text/html');
    const content = doc.querySelector('.biography-text .field__item');
    return content ? content.textContent.trim() : null;
}

export async function handleReadBiography(biographyUrl) {
    cancelSpeech();
    isSpeaking = true;

    try {
        const text = await getBiographyText(biographyUrl);
        if (!isSpeaking || !text) return;
        const cleanedText = text.replace(/<[^>]*>?/gm, '');

        try {
            // Die "Beste Lösung"
            await speakWithPreloading(cleanedText);
        } catch (e) {
            if (isSpeaking) {
                mylog("Google fehlgeschlagen, nutze Browser-Fallback...");
                await speakChunksFallback(cleanedText);
            }
        }
    } catch (error) {
        mylog(`Fehler: ${error.message}`);
    } finally {
        isSpeaking = false;
    }
}