from pathlib import Path
import hashlib
import os
import asyncio

import edge_tts
from mutagen.mp3 import MP3

from fluxion.scene.scene import Scene
from fluxion import config
from fluxion.utils.file_ops import guarantee_existence

class VoiceOverScene(Scene):
    """A Scene that adds neural voiceover capabilities using Edge-TTS."""
    
    def setup(self):
        super().setup()
        self.audio_dir = Path(config.get_dir("media_dir")) / "voiceovers"
        guarantee_existence(self.audio_dir)
        
    def speak(self, text, voice='en-US-ChristopherNeural', rate='+0%', wait_buffer=0.5):
        """
        Generates Neural TTS audio for the text, plays it, and waits for its duration.
        
        Parameters
        ----------
        text : str
            The text to speak.
        voice : str
            The neural voice code (default 'en-US-ChristopherNeural').
            Alternatives: 'en-US-AriaNeural', 'en-GB-SoniaNeural', etc.
        rate : str
            Speaking rate adjustment (e.g., '+10%', '-5%').
        wait_buffer : float
            Extra time to wait after the speech ends (default 0.5s).
        """
        
        # 1. Generate unique filename based on parameters
        hash_str = hashlib.md5(f"{text}_{voice}_{rate}".encode()).hexdigest()
        filename = f"{hash_str}.mp3"
        filepath = self.audio_dir / filename
        
        # 2. Generate audio if it doesn't exist
        if not filepath.exists():
            asyncio.run(self._generate_audio(text, voice, rate, str(filepath)))
            
        # 3. Get Audio Duration
        try:
            audio = MP3(filepath)
            duration = audio.info.length
        except Exception as e:
            print(f"Warning: Could not determine audio length: {e}")
            duration = 2 # Fallback
            
        # 4. Add Sound to Scene
        self.add_sound(str(filepath))
        
        # 5. Wait for the duration
        self.wait(duration + wait_buffer)
        
        return duration

    async def _generate_audio(self, text, voice, rate, output_path):
        """Async helper to generate audio using edge-tts"""
        communicate = edge_tts.Communicate(text, voice, rate=rate)
        await communicate.save(output_path)
