

import os
import tempfile
import uuid
import json
import asyncio
from datetime import datetime
import sys
import g4f
from ttsfm import TTSClient, Voice, AudioFormat
from pydub import AudioSegment
import traceback

# Add path to parent directory to import shared modules
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from search_ai.db import log_ai_request

# Load API key from environment variable or use a placeholder for development
TTSFM_API_KEY = os.environ.get("TTSFM_API_KEY", "your-api-key-here")

# Initialize TTS client
tts_client = TTSClient(api_key=TTSFM_API_KEY)

# Directory to store generated audio files
AUDIO_OUTPUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "generated_audio")
os.makedirs(AUDIO_OUTPUT_DIR, exist_ok=True)

# Supported voice models
VOICE_MODELS = {
    "en-US": [
        {"id": "nova", "name": "Nova (Female)", "description": "Clear and professional female voice"},
        {"id": "onyx", "name": "Onyx (Male)", "description": "Deep and engaging male voice"},
        {"id": "shimmer", "name": "Shimmer (Female)", "description": "Warm and friendly female voice"},
        {"id": "sage", "name": "Sage (Male)", "description": "Thoughtful and measured male voice"}
    ],
    "hi-IN": [
        {"id": "nova", "name": "Priya (Female)", "description": "Clear Hindi female voice"},
        {"id": "onyx", "name": "Arjun (Male)", "description": "Professional Hindi male voice"}
    ],
    "ne-NP": [
        {"id": "nova", "name": "Anjali (Female)", "description": "Natural Nepali female voice"},
        {"id": "onyx", "name": "Dipak (Male)", "description": "Clear Nepali male voice"}
    ],
    "es-ES": [
        {"id": "spanish-female", "name": "Sofia (Female)", "description": "Natural Spanish female voice"},
        {"id": "spanish-male", "name": "Diego (Male)", "description": "Warm Spanish male voice"}
    ],
    "fr-FR": [
        {"id": "french-female", "name": "Claire (Female)", "description": "Elegant French female voice"},
        {"id": "french-male", "name": "Jean (Male)", "description": "Sophisticated French male voice"}
    ],
    "de-DE": [
        {"id": "german-female", "name": "Hannah (Female)", "description": "Clear German female voice"},
        {"id": "german-male", "name": "Max (Male)", "description": "Authoritative German male voice"}
    ]
}


async def generate_teacher_summary(content, language_code="en-US"):
    """
    Generate a teacher-like summarized version of content using G4F
    
    Args:
        content (str): Original content to summarize
        language_code (str): Language code to generate summary in
    
    Returns:
        str: Summarized content in teacher-like voice
    """
    try:
        # Define language-specific prompts
        prompts = {
    "en-US": "Transform this content into a warm, engaging explanation as if you're a caring teacher speaking directly to your students. Use natural speech patterns with pauses, enthusiasm, and emotional warmth. Include conversational phrases like 'Now, here's the interesting part...' or 'You know what's really cool about this?' Make it sound spontaneous and personal, as if you're genuinely excited to share this knowledge. Keep the key concepts but express them in a way that feels like a friendly conversation rather than reading from a textbook. IMPORTANT: Never mention that you are summarizing, transforming, or converting content - just provide the natural teacher explanation directly:",

    "hi-IN": "इस सामग्री को एक प्रेमपूर्ण, आकर्षक व्याख्या में बदलें जैसे कि आप एक स्नेही शिक्षक हैं जो अपने छात्रों से सीधे बात कर रहे हैं। प्राकृतिक भाषण पैटर्न का उपयोग करें जिसमें रुकावट, उत्साह और भावनात्मक गर्मजोशी हो। वार्तालाप वाक्यांशों को शामिल करें जैसे 'अब, यहाँ दिलचस्प बात है...' या 'आप जानते हैं इसके बारे में क्या वास्तव में अद्भुत है?' इसे सहज और व्यक्तिगत लगने दें, जैसे कि आप वास्तव में इस ज्ञान को साझा करने के लिए उत्साहित हैं। मुख्य अवधारणाओं को रखें लेकिन उन्हें इस तरह व्यक्त करें जो पाठ्यपुस्तक पढ़ने के बजाय एक मित्रवत बातचीत की तरह लगे। महत्वपूर्ण: कभी भी यह न बताएं कि आप सामग्री को सारांशित, रूपांतरित या परिवर्तित कर रहे हैं - बस सीधे प्राकृतिक शिक्षक व्याख्या प्रदान करें:",
    
    "ne-NP": "यस सामग्रीलाई एक न्यानो र आकर्षक व्याख्यामा परिवर्तन गर्नुहोस्, जस्तै तपाईं आफ्ना विद्यार्थीहरूसँग प्रत्यक्ष कुरा गर्ने एक हेरचाह गर्ने शिक्षक हुनुहुन्छ। प्राकृतिक बोली ढाँचाहरू प्रयोग गर्नुहोस् जसमा विराम, उत्साह र भावनात्मक न्यानोपन छ। संवादात्मक वाक्यांशहरू समावेश गर्नुहोस् जस्तै 'अब, यहाँ रोचक भाग छ...' वा 'के तपाईंलाई थाहा छ यसको बारेमा के साँच्चै राम्रो छ?' यसलाई स्वाभाविक र व्यक्तिगत सुनिने बनाउनुहोस्, मानौं तपाईं यो ज्ञान बाँड्न वास्तवमै उत्साहित हुनुहुन्छ। मुख्य अवधारणाहरू राख्नुहोस् तर तिनीहरूलाई यस्तो तरिकाले व्यक्त गर्नुहोस् जुन पाठ्यपुस्तक पढ्नु भन्दा मित्रवत कुराकानी जस्तो लाग्छ। महत्त्वपूर्ण: कहिल्यै पनि उल्लेख नगर्नुहोस् कि तपाईं सामग्री संक्षिप्त, रूपान्तरण वा परिवर्तन गर्दै हुनुहुन्छ - केवल प्रत्यक्ष रूपमा प्राकृतिक शिक्षक व्याख्या प्रदान गर्नुहोस्:",

    "es-ES": "Transforma este contenido en una explicación cálida y atractiva como si fueras un profesor cariñoso hablando directamente con tus estudiantes. Usa patrones de habla naturales con pausas, entusiasmo y calidez emocional. Incluye frases conversacionales como 'Ahora, aquí está la parte interesante...' o '¿Sabes qué es realmente genial de esto?' Haz que suene espontáneo y personal, como si estuvieras genuinamente emocionado de compartir este conocimiento. Mantén los conceptos clave pero exprésalos de manera que se sienta como una conversación amistosa en lugar de leer un libro de texto. IMPORTANTE: Nunca menciones que estás resumiendo, transformando o convirtiendo contenido - solo proporciona la explicación natural del profesor directamente:",

    "fr-FR": "Transformez ce contenu en une explication chaleureuse et engageante comme si vous étiez un professeur bienveillant parlant directement à vos élèves. Utilisez des modèles de parole naturels avec des pauses, de l'enthousiasme et de la chaleur émotionnelle. Incluez des phrases conversationnelles comme 'Maintenant, voici la partie intéressante...' ou 'Vous savez ce qui est vraiment cool à ce sujet ?' Faites en sorte que cela sonne spontané et personnel, comme si vous étiez vraiment excité de partager ces connaissances. Gardez les concepts clés mais exprimez-les d'une manière qui ressemble à une conversation amicale plutôt qu'à la lecture d'un manuel. IMPORTANT: Ne mentionnez jamais que vous résumez, transformez ou convertissez du contenu - fournissez simplement l'explication naturelle du professeur directement:",

    "de-DE": "Verwandeln Sie diesen Inhalt in eine warmherzige, fesselnde Erklärung, als wären Sie ein fürsorglicher Lehrer, der direkt mit seinen Schülern spricht. Verwenden Sie natürliche Sprachmuster mit Pausen, Begeisterung und emotionaler Wärme. Fügen Sie gesprächige Phrasen hinzu wie 'Jetzt kommt der interessante Teil...' oder 'Wissen Sie, was wirklich cool daran ist?' Lassen Sie es spontan und persönlich klingen, als wären Sie wirklich begeistert, dieses Wissen zu teilen. Behalten Sie die Schlüsselkonzepte bei, aber drücken Sie sie so aus, dass es sich wie ein freundliches Gespräch anfühlt, anstatt aus einem Lehrbuch zu lesen:",

    "pt-BR": "Transforme este conteúdo em uma explicação calorosa e envolvente como se você fosse um professor carinhoso falando diretamente com seus alunos. Use padrões de fala naturais com pausas, entusiasmo e calor emocional. Inclua frases conversacionais como 'Agora, aqui está a parte interessante...' ou 'Vocês sabem o que é realmente legal sobre isso?' Faça soar espontâneo e pessoal, como se você estivesse genuinamente empolgado para compartilhar esse conhecimento. Mantenha os conceitos-chave, mas expresse-os de uma forma que pareça uma conversa amigável em vez de ler um livro didático:",

    "ja-JP": "この内容を、あなたが思いやりのある先生として生徒に直接話しかけているような、温かく魅力的な説明に変換してください。自然な話し方のパターンを使用し、間を取り、熱意と感情的な温かさを込めてください。「さあ、ここからが面白いところです...」や「これについて本当にすごいことを知っていますか？」などの会話的なフレーズを含めてください。この知識を共有することに本当に興奮しているかのように、自然で個人的に聞こえるようにしてください。重要な概念は保持しながら、教科書を読むのではなく、友好的な会話のように感じられる方法で表現してください:",

    "ko-KR": "이 내용을 마치 당신이 학생들과 직접 대화하는 따뜻한 선생님인 것처럼 따뜻하고 매력적인 설명으로 바꿔주세요. 자연스러운 말투에 휴지부, 열정, 감정적 따뜻함을 담아 사용하세요. '자, 여기서 흥미로운 부분이 나와요...' 또는 '이것에 대해 정말 멋진 점이 뭔지 알아요?'와 같은 대화체 표현을 포함하세요. 마치 이 지식을 공유하는 것에 정말로 흥미진진해하는 것처럼 자연스럽고 개인적으로 들리도록 만드세요. 핵심 개념은 유지하되 교과서를 읽는 것이 아닌 친근한 대화처럼 느껴지는 방식으로 표현하세요:"
};      
        # Use default English prompt if language not supported
        prompt = prompts.get(language_code, prompts["en-US"])
        
        # Prepare the message for G4F
        full_prompt = f"{prompt}\n\n{content}"
        
        # Log the AI request
        request_id = str(uuid.uuid4())
        log_ai_request(
            request_id=request_id,
            request_type="teacher_summary",
            request_data={"content": content[:500] + "..." if len(content) > 500 else content},
            model="gpt-5",
            provider="PollinationsAI",
            tokens_used=len(content.split()) * 1.3  # Rough estimation
        )
        
        try:
            print(f"Generating teacher summary using g4f default provider")
            # Let g4f use its default provider selection mechanism
            response = await g4f.ChatCompletion.create_async(
                model="gpt-5",
                provider="PollinationsAI",
                messages=[{"role": "user", "content": full_prompt}],
                timeout=60
            )
            
            if response and len(response) > 100:  # Ensure we got a meaningful response
                summary = response
                print(f"Successfully generated summary")
            else:
                # If response is too short, use fallback
                print(f"Generated response too short, using fallback")
                raise Exception("Response too short")
                
        except Exception as e:
            print(f"Error with g4f: {str(e)}")
            # Use fallback summarization
            print("Using fallback summarization")
            # Simple fallback summary by extracting key sentences
            sentences = content.split('.')
            if len(sentences) > 10:
                summary = '. '.join(sentences[:3] + sentences[len(sentences)//2:len(sentences)//2+2] + sentences[-3:]) + '.'
            else:
                summary = content
            
            # Add teacher-like introduction
            summary = f"Let me explain this in a simpler way. {summary} I hope that makes sense!"
        
        # Log the completion
        log_ai_request(
            request_id=request_id,
            response_data={"summary": summary[:500] + "..." if len(summary) > 500 else summary},
            completion_time=datetime.now(),
            status="success"
        )
        
        return summary
    except Exception as e:
        print(f"Error in teacher summary generation: {str(e)}")
        # Return original content if summarization fails
        return content

def get_voice_enum(voice_id):
    """Convert voice ID string to Voice enum"""
    voice_mapping = {
        'alloy': Voice.ALLOY,
        'ash': Voice.ASH,
        'ballad': Voice.BALLAD, 
        'coral': Voice.CORAL,
        'echo': Voice.ECHO,
        'fable': Voice.FABLE,
        'nova': Voice.NOVA,
        'onyx': Voice.ONYX,
        'sage': Voice.SAGE,
        'shimmer': Voice.SHIMMER,
        'verse': Voice.VERSE
    }
    return voice_mapping.get(voice_id.lower(), Voice.NOVA)

def get_available_languages():
    """Return a list of available languages for TTS"""
    return list(VOICE_MODELS.keys())

def get_voices_for_language(language_code):
    """Return available voices for a specific language"""
    return VOICE_MODELS.get(language_code, [])

def get_all_voices():
    """Return all available voices organized by language"""
    return VOICE_MODELS

def clean_text_for_tts(text):
    """Clean and prepare text for TTS processing"""
    # Remove markdown syntax and formatting that might disrupt speech
    cleaned_text = text
    
    # Remove code blocks
    cleaned_text = cleaned_text.replace("```", "Code block: ")
    
    # Remove inline code
    cleaned_text = cleaned_text.replace("`", "")
    
    # Convert markdown headings to sentences
    for i in range(6, 0, -1):
        heading_marker = '#' * i + ' '
        cleaned_text = cleaned_text.replace(heading_marker, "")
    
    # Replace bullet points with verbal pauses
    cleaned_text = cleaned_text.replace("* ", ", ")
    cleaned_text = cleaned_text.replace("- ", ", ")
    
    # Remove markdown links and just keep the text
    # Find all occurrences of [text](url) and replace with just text
    import re
    # cleaned_text = re.sub(r'\[([^\]]+)\]\([^)]+\)', r'\1', cleaned_text)
    
    # Remove any remaining special characters that might interfere with TTS
    # cleaned_text = re.sub(r'[*_~]', '', cleaned_text)
    
    # Remove problematic Unicode characters that might cause encoding issues
    # Replace common problematic characters with text equivalents
    unicode_replacements = {
        '⏳': 'Time',
        '✅': 'Check',
        '❌': 'X',
        '⚠️': 'Warning',
        '📋': 'List',
        '🔍': 'Search',
        '💡': 'Idea',
        '📝': 'Note',
        '⭐': 'Star',
        '🚀': 'Rocket'
    }
    
    for unicode_char, replacement in unicode_replacements.items():
        cleaned_text = cleaned_text.replace(unicode_char, replacement)
    
    # Remove any remaining non-ASCII characters that might cause issues
    # cleaned_text = re.sub(r'[^\x00-\x7F]+', ' ', cleaned_text)
    
    # Clean up extra spaces
    cleaned_text = re.sub(r'\s+', ' ', cleaned_text).strip()
    
    return cleaned_text

async def generate_audio_async(text, language_code="en-US", voice_id="sage", format=None, speed=1.0, summarize=True):
    """
    Async version of generate_audio that handles the G4F summarization
    """
    try:
        # First, generate a teacher-like summary if requested
        if summarize:
            print("Generating teacher-like summary of content...")
            summarized_text = await generate_teacher_summary(text, language_code)
            print(f"Summary generated: {len(summarized_text)} characters")
        else:
            summarized_text = text
            
        # Now proceed with TTS generation using the summarized text
        return generate_audio(summarized_text, language_code, voice_id, format, speed)
        
    except Exception as e:
        error_message = str(e)
        print(f"Error in async audio generation: {error_message}")
        return {
            "status": "error",
            "message": f"Failed to generate audio asynchronously: {error_message}"
        }
def generate_audio(text, language_code="en-US", voice_id="sage", format=None, speed=1.0, summarize=False):
    """
    Generate audio from text using ttsfm (WAV format only)
    
    Args:
        text (str): Text to convert to speech
        language_code (str): Language code (e.g., "en-US", "hi-IN")
        voice_id (str): Voice ID to use
        format: Ignored - always uses WAV format
        speed (float): Speech speed factor (0.5 to 2.0)
        summarize (bool): If True, summarize content first (handled by async version)
        
    Returns:
        dict: Response containing status and file information
    """
    # For synchronous calls with summarization requested, we need to run the async version
    if summarize:
        print("Synchronous call with summarize=True, running async loop")
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        result = loop.run_until_complete(generate_audio_async(text, language_code, voice_id, format, speed))
        loop.close()
        return result
    
    try:
        # Clean text for TTS
        cleaned_text = clean_text_for_tts(text)
        
        # Generate a unique filename base
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename_base = f"tts_{language_code}_{timestamp}_{uuid.uuid4().hex[:8]}"
        
        # Always use WAV format
        extension = "wav"
        filename = f"{filename_base}.{extension}"
        output_path = os.path.join(AUDIO_OUTPUT_DIR, filename)
        
        # Get the proper voice enum value
        voice = get_voice_enum(voice_id)
        
        # Generate audio using the simpler long text method
        responses = tts_client.generate_speech_long_text(
            text=cleaned_text,
            voice=voice,
            # response_format=AudioFormat.WAV,
            max_length=1000,
            preserve_words=True
        )
        
        # If only one response, save it directly
        if len(responses) == 1:
            # Save using the TTSResponse's save_to_file method
            responses[0].save_to_file(output_path)
            print(f"Audio saved to: {output_path}")
        else:
            # Multiple responses - use pydub to merge chunks into single file
            print(f"Processing {len(responses)} audio chunks...")
            
            # Initialize empty audio segment for combining
            combined_audio = None
            saved_chunks = []
            
            # Save chunks in WAV format
            for i, response in enumerate(responses):
                wav_filename = f"{filename_base}_temp_part{i}.wav"
                wav_path = os.path.join(AUDIO_OUTPUT_DIR, wav_filename)
                
                try:
                    response.save_to_file(wav_path)
                    if os.path.exists(wav_path):
                        print(f"Saved chunk {i + 1}/{len(responses)} as WAV")
                        saved_chunks.append({"path": wav_path, "format": "wav"})
                    else:
                        print(f"Failed to save chunk {i + 1}: file not created")
                except Exception as e:
                    print(f"Error saving chunk {i + 1} as WAV: {str(e)}")
                    print(f"Failed to save chunk {i + 1}")
            
            # Use WAV format
            output_path = os.path.join(AUDIO_OUTPUT_DIR, f"{filename_base}.wav")
            print(f"Output will be: {output_path}")
            
            # Process the chunks if we have any
            if saved_chunks:
                # Initialize with the first chunk
                first_chunk = saved_chunks[0]["path"]
                combined_audio = AudioSegment.from_wav(first_chunk)
                
                print(f"Started with chunk 1: {len(combined_audio)/1000:.2f}s")
                
                # Add each subsequent chunk
                for i, chunk_data in enumerate(saved_chunks[1:], 2):
                    try:
                        chunk_path = chunk_data["path"]
                        next_chunk = AudioSegment.from_wav(chunk_path)
                        
                        combined_audio += next_chunk
                        print(f"Combined chunk {i}/{len(saved_chunks)}")
                    except Exception as e:
                        print(f"Error adding chunk {i}: {str(e)}")
                
                # Export the final combined audio in WAV format
                combined_audio.export(output_path, format="wav")
                print(f"Combined audio exported to: {output_path} ({len(combined_audio)/1000:.2f}s)")
                
                # Set the filename to use in the response
                filename = f"{filename_base}.wav"
                
                # Clean up temporary chunk files
                for chunk_data in saved_chunks:
                    try:
                        if os.path.exists(chunk_data["path"]):
                            os.remove(chunk_data["path"])
                    except OSError as e:
                        print(f"Warning: Could not remove temporary file {chunk_data['path']}: {e}")
                
                print(f"Successfully processed {len(saved_chunks)} audio chunks")
            else:
                raise Exception("Failed to save any audio chunks")
        
        # Return success response with file details
        return {
            "status": "success",
            "message": "Audio generated successfully",
            "filename": filename,
            "path": output_path,
            "url": f"/api/audio_generation/audio/{filename}",
            "format": "wav",
            "parts": len(responses)
        }
        
    except Exception as e:
        error_message = str(e)
        print(f"Error generating audio: {error_message}")
        
        return {
            "status": "error",
            "message": f"Failed to generate audio: {error_message}"
        }
def get_audio_file_path(filename):
    """Get the full path to an audio file"""
    return os.path.join(AUDIO_OUTPUT_DIR, filename)

# Audio file cleanup (optional background task)
def cleanup_old_audio_files(max_age_hours=24):
    """Remove audio files older than the specified age"""
    try:
        current_time = datetime.now()
        deleted_count = 0
        
        for filename in os.listdir(AUDIO_OUTPUT_DIR):
            if not filename.startswith('tts_'):
                continue
                
            file_path = os.path.join(AUDIO_OUTPUT_DIR, filename)
            file_age = datetime.fromtimestamp(os.path.getctime(file_path))
            age_hours = (current_time - file_age).total_seconds() / 3600
            
            if age_hours > max_age_hours:
                os.remove(file_path)
                deleted_count += 1
                
        return {"deleted_count": deleted_count}
    except Exception as e:
        print(f"Error during audio cleanup: {e}")
        return {"error": str(e)}