/**
 * Microsoft Translator - Frontend Implementation
 * Uses Edge browser's free translation API
 */

class MicrosoftTranslator {
    constructor() {
        this.authToken = null;
        this.tokenExpiry = null;
        this.authUrl = 'https://edge.microsoft.com/translate/auth';
        this.translateUrl = 'https://api-edge.cognitive.microsofttranslator.com/translate';
    }

    /**
     * Get authentication token from Microsoft Edge
     */
    async getAuthToken() {
        console.log('[MS Translator] Starting authentication...');

        // Check if we have a valid cached token
        if (this.authToken && this.tokenExpiry && Date.now() < this.tokenExpiry) {
            console.log('[MS Translator] Using cached token');
            return this.authToken;
        }

        try {
            console.log('[MS Translator] Fetching auth token from:', this.authUrl);

            const response = await fetch(this.authUrl, {
                method: 'GET',
                headers: {
                    'Accept': '*/*'
                }
            });

            console.log('[MS Translator] Auth response status:', response.status);
            console.log('[MS Translator] Auth response headers:', [...response.headers.entries()]);

            if (!response.ok) {
                const errorBody = await response.text();
                console.error('[MS Translator] Auth failed with body:', errorBody);
                throw new Error(`Auth failed: ${response.status} - ${errorBody}`);
            }

            this.authToken = await response.text();
            // Token expires in 10 minutes, we'll refresh after 9 minutes
            this.tokenExpiry = Date.now() + (9 * 60 * 1000);

            console.log('[MS Translator] Auth token obtained successfully');
            console.log('[MS Translator] Token preview:', this.authToken.substring(0, 20) + '...');
            return this.authToken;

        } catch (error) {
            console.error('[MS Translator] Auth error details:', error);
            console.error('[MS Translator] Error type:', error.constructor.name);
            console.error('[MS Translator] Error message:', error.message);
            throw new Error('Failed to authenticate with Microsoft Translator: ' + error.message);
        }
    }

    /**
     * Translate text using Microsoft Translator API
     * @param {string} text - Text to translate
     * @param {string} fromLang - Source language (default: 'en')
     * @param {string} toLang - Target language (default: 'zh-Hans')
     * @returns {Promise<string>} - Translated text
     */
    async translate(text, fromLang = 'en', toLang = 'zh-Hans') {
        console.log('[MS Translator] Starting translation...');
        console.log('[MS Translator] Text to translate:', text.substring(0, 100) + '...');
        console.log('[MS Translator] From language:', fromLang);
        console.log('[MS Translator] To language:', toLang);

        try {
            // Preserve multiple newlines by replacing them with placeholders
            // Use underscores which are less likely to be translated
            const newlineMap = new Map();
            let newlineIndex = 0;
            let processedText = text;

            // Replace consecutive newlines (2 or more) with unique placeholders
            processedText = text.replace(/\n{2,}/g, (match) => {
                const placeholder = `___MSNL${newlineIndex}_${match.length}___`;
                newlineMap.set(placeholder, match);
                newlineIndex++;
                return placeholder;
            });

            console.log('[MS Translator] Preserved', newlineMap.size, 'newline sequences');
            console.log('[MS Translator] Newline placeholders:', Array.from(newlineMap.keys()));

            // Get auth token
            const token = await this.getAuthToken();

            // Prepare request
            const url = new URL(this.translateUrl);
            url.searchParams.append('api-version', '3.0');
            url.searchParams.append('from', fromLang);
            url.searchParams.append('to', toLang);

            console.log('[MS Translator] Translation URL:', url.toString());

            const requestBody = [{ text: processedText }];

            const response = await fetch(url.toString(), {
                method: 'POST',
                headers: {
                    'Authorization': `Bearer ${token}`,
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                },
                body: JSON.stringify(requestBody)
            });

            console.log('[MS Translator] Translation response status:', response.status);

            if (!response.ok) {
                const errorBody = await response.text();
                console.error('[MS Translator] Translation failed with body:', errorBody);
                throw new Error(`Translation failed: ${response.status} - ${errorBody}`);
            }

            const result = await response.json();

            if (result && result[0] && result[0].translations && result[0].translations[0]) {
                let translatedText = result[0].translations[0].text;

                console.log('[MS Translator] Before restoring newlines:', translatedText.substring(0, 300));
                console.log('[MS Translator] Translation contains placeholders:', Array.from(newlineMap.keys()).filter(p => translatedText.includes(p)));

                // Restore the preserved newlines
                for (const [placeholder, originalNewlines] of newlineMap.entries()) {
                    const count = (translatedText.match(new RegExp(placeholder.replace(/[_]/g, '\\$&'), 'g')) || []).length;
                    console.log(`[MS Translator] Replacing ${placeholder} (appears ${count} times) with ${originalNewlines.length} newlines`);

                    // Direct replacement using split/join
                    translatedText = translatedText.split(placeholder).join(originalNewlines);
                }

                console.log('[MS Translator] After restoring newlines:', translatedText.substring(0, 300));
                console.log('[MS Translator] Translation successful, restored', newlineMap.size, 'newline sequences');
                return translatedText;
            } else {
                console.error('[MS Translator] Invalid response format:', result);
                throw new Error('Invalid response format');
            }

        } catch (error) {
            console.error('[MS Translator] Translation error:', error);
            console.error('[MS Translator] Error type:', error.constructor.name);
            console.error('[MS Translator] Error message:', error.message);
            throw error;
        }
    }

    /**
     * Translate multiple texts in batch
     * @param {string[]} texts - Array of texts to translate
     * @param {string} fromLang - Source language
     * @param {string} toLang - Target language
     * @returns {Promise<string[]>} - Array of translated texts
     */
    async translateBatch(texts, fromLang = 'en', toLang = 'zh-Hans') {
        try {
            // Get auth token
            const token = await this.getAuthToken();

            // Prepare request
            const url = new URL(this.translateUrl);
            url.searchParams.append('api-version', '3.0');
            url.searchParams.append('from', fromLang);
            url.searchParams.append('to', toLang);

            // Microsoft API supports up to 100 texts per request
            const maxBatchSize = 100;
            const batches = [];

            for (let i = 0; i < texts.length; i += maxBatchSize) {
                batches.push(texts.slice(i, i + maxBatchSize));
            }

            const results = [];

            for (const batch of batches) {
                const requestBody = batch.map(text => ({ text }));

                const response = await fetch(url.toString(), {
                    method: 'POST',
                    headers: {
                        'Authorization': `Bearer ${token}`,
                        'Content-Type': 'application/json',
                        'Accept': 'application/json'
                    },
                    body: JSON.stringify(requestBody)
                });

                if (!response.ok) {
                    throw new Error(`Batch translation failed: ${response.status}`);
                }

                const batchResult = await response.json();
                const translations = batchResult.map(item =>
                    item.translations && item.translations[0] ? item.translations[0].text : ''
                );

                results.push(...translations);
            }

            return results;

        } catch (error) {
            console.error('Microsoft Translator batch error:', error);
            throw error;
        }
    }

    /**
     * Detect language of text
     * @param {string} text - Text to detect language
     * @returns {Promise<string>} - Detected language code
     */
    async detectLanguage(text) {
        try {
            const token = await this.getAuthToken();

            const url = 'https://api-edge.cognitive.microsofttranslator.com/detect?api-version=3.0';

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'Authorization': `Bearer ${token}`,
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                },
                body: JSON.stringify([{ text: text }])
            });

            if (!response.ok) {
                throw new Error(`Language detection failed: ${response.status}`);
            }

            const result = await response.json();

            if (result && result[0] && result[0].language) {
                return result[0].language;
            } else {
                return 'en'; // Default to English
            }

        } catch (error) {
            console.error('Language detection error:', error);
            return 'en'; // Default to English on error
        }
    }
}

// Export singleton instance
const microsoftTranslator = new MicrosoftTranslator();
