"""
Text-to-Speech Service for Video Narration
Supports Arabic and English voice generation for campaign videos
"""
import os
import tempfile
import subprocess
import requests
from typing import Dict, Optional
from flask import current_app


class TTSService:
    """Text-to-Speech service for generating video narration in multiple languages."""

    def __init__(self):
        self.elevenlabs_api_key = None
        self.google_tts_api_key = None
        self._load_api_keys()

    def _load_api_keys(self):
        """Load TTS API keys from environment or config."""
        self.elevenlabs_api_key = os.getenv("ELEVENLABS_API_KEY")
        self.google_tts_api_key = os.getenv("GOOGLE_TTS_API_KEY")

    def generate_arabic_narration(self, text: str, output_path: str, voice: str = "ar-EG") -> bool:
        """
        Generate Arabic narration using Google TTS or alternative service.

        Args:
            text: Arabic text to convert to speech
            output_path: Where to save the audio file
            voice: Voice ID (default: ar-EG for Arabic)

        Returns:
            bool: True if successful, False otherwise
        """
        try:
            # Try Google TTS first (free tier available)
            if self._try_google_tts(text, output_path, voice):
                return True

            # Fallback to pyttsx3 if available
            if self._try_pyttsx3(text, output_path, voice):
                return True

            # Fallback to espeak if available
            if self._try_espeak(text, output_path, voice):
                return True

            current_app.logger.error("No TTS service available")
            return False

        except Exception as e:
            current_app.logger.error(f"Arabic TTS generation failed: {e}")
            return False

    def _try_google_tts(self, text: str, output_path: str, voice: str = "ar-EG") -> bool:
        """Try Google Translate TTS API (free tier)."""
        try:
            # Google Translate TTS API (free, no key needed for basic usage)
            # Using the unofficial API endpoint
            base_url = "https://translate.google.com/translate_tts"
            params = {
                "ie": "UTF-8",
                "q": text[:200],  # Limit text length
                "tl": voice,
                "client": "tw-ob"
            }

            response = requests.get(base_url, params=params, timeout=30)

            if response.status_code == 200 and response.content:
                # Save the audio content
                with open(output_path, 'wb') as f:
                    f.write(response.content)
                current_app.logger.info(f"Generated Arabic TTS using Google TTS: {output_path}")
                return True

            return False

        except Exception as e:
            current_app.logger.warning(f"Google TTS failed: {e}")
            return False

    def _try_pyttsx3(self, text: str, output_path: str, voice: str = "arabic") -> bool:
        """Try pyttsx3 offline TTS."""
        try:
            import pyttsx3

            # Initialize TTS engine
            tts = pyttsx3.init()

            # Set properties for Arabic
            tts.setProperty('voice', voice)
            tts.setProperty('rate', 150)  # Slightly slower for Arabic clarity
            tts.setProperty('volume', 1.0)

            # Save to file
            tts.save_to_file(text, output_path)
            current_app.logger.info(f"Generated Arabic TTS using pyttsx3: {output_path}")
            return True

        except ImportError:
            # pyttsx3 not installed
            return False
        except Exception as e:
            current_app.logger.warning(f"pyttsx3 TTS failed: {e}")
            return False

    def _try_espeak(self, text: str, output_path: str, voice: str = "ar") -> bool:
        """Try espeak-ng TTS engine."""
        try:
            # Generate temporary WAV file first
            import tempfile
            with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as tmp_wav:
                wav_path = tmp_wav.name

            # Generate speech to WAV file
            espeak_cmd = [
                'espeak-ng',
                '-v', voice,
                '-s', '150',  # Speed
                text,
                '-w', wav_path
            ]

            espeak_result = subprocess.run(espeak_cmd, capture_output=True, text=True, timeout=60)

            if espeak_result.returncode != 0:
                current_app.logger.warning(f"espeak-ng generation failed: {espeak_result.stderr}")
                return False

            # Convert WAV to MP3 using ffmpeg
            ffmpeg_cmd = [
                'ffmpeg',
                '-i', wav_path,
                '-codec:a', 'libmp3lame',
                '-qscale:a', '2',
                '-y',
                output_path
            ]

            ffmpeg_result = subprocess.run(ffmpeg_cmd, capture_output=True, text=True, timeout=60)

            # Clean up temporary WAV file
            try:
                os.unlink(wav_path)
            except:
                pass

            if ffmpeg_result.returncode == 0:
                current_app.logger.info(f"Generated Arabic TTS using espeak-ng: {output_path}")
                return True
            else:
                current_app.logger.warning(f"ffmpeg conversion failed: {ffmpeg_result.stderr}")
                return False

        except FileNotFoundError:
            # espeak-ng not installed
            return False
        except Exception as e:
            current_app.logger.warning(f"espeak-ng TTS failed: {e}")
            return False

    def generate_narration_audio(self, text: str, language: str = "ar", output_path: Optional[str] = None) -> Optional[str]:
        """
        Generate narration audio for video using TTS.

        Args:
            text: Text to convert to speech
            language: Language code ('ar' or 'en')
            output_path: Optional output file path

        Returns:
            str: Path to generated audio file, or None if failed
        """
        import uuid

        if not output_path:
            # Create temporary path
            output_path = f"/tmp/tts_{uuid.uuid4().hex}.mp3"

        try:
            if language == "ar":
                success = self.generate_arabic_narration(text, output_path)
            else:
                # For English, use similar approach
                success = self._try_google_tts(text, output_path, "en-US")

            if success:
                return output_path
            else:
                return None

        except Exception as e:
            current_app.logger.error(f"TTS generation failed: {e}")
            return None

    def add_audio_to_video(self, video_path: str, audio_path: str, output_path: str) -> bool:
        """
        Add audio narration to video using ffmpeg.

        Args:
            video_path: Path to input video
            audio_path: Path to audio file
            output_path: Path for output video

        Returns:
            bool: True if successful, False otherwise
        """
        try:
            # Check if ffmpeg is available
            subprocess.run(['ffmpeg', '-version'], capture_output=True, check=True)

            # Add audio to video using ffmpeg
            cmd = [
                'ffmpeg',
                '-i', video_path,
                '-i', audio_path,
                '-c:v', 'copy',  # Copy video without re-encoding
                '-c:a', 'aac',
                '-shortest',
                '-y',
                output_path
            ]

            result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)

            if result.returncode == 0:
                current_app.logger.info(f"Audio added to video successfully: {output_path}")
                return True
            else:
                current_app.logger.error(f"ffmpeg audio mixing failed: {result.stderr}")
                return False

        except FileNotFoundError:
            current_app.logger.error("ffmpeg not found for audio mixing")
            return False
        except Exception as e:
            current_app.logger.error(f"Audio addition failed: {e}")
            return False

    def get_available_voices(self, language: str = "ar") -> list:
        """Get list of available voices for a language."""
        voices = []

        if language == "ar":
            voices = [
                {"id": "ar-EG", "name": "Arabic (Egypt)", "quality": "Good"},
                {"id": "ar-SA", "name": "Arabic (Saudi Arabia)", "quality": "Good"},
                {"id": "ar-AE", "name": "Arabic (UAE)", "quality": "Good"},
            ]
        elif language == "en":
            voices = [
                {"id": "en-US", "name": "English (US)", "quality": "Excellent"},
                {"id": "en-GB", "name": "English (UK)", "quality": "Excellent"},
            ]

        return voices

    def check_tts_availability(self) -> Dict[str, bool]:
        """Check which TTS services are available."""
        availability = {
            "google_tts": self._check_google_tts(),
            "pyttsx3": self._check_pyttsx3(),
            "espeak": self._check_espeak(),
        }
        return availability

    def _check_google_tts(self) -> bool:
        """Check if Google TTS is accessible."""
        try:
            response = requests.get("https://translate.google.com/translate_tts", timeout=10)
            return response.status_code == 200
        except:
            return False

    def _check_pyttsx3(self) -> bool:
        """Check if pyttsx3 is available."""
        try:
            import pyttsx3
            return True
        except ImportError:
            return False

    def _check_espeak(self) -> bool:
        """Check if espeak-ng is available."""
        try:
            subprocess.run(['espeak-ng', '--version'], capture_output=True, check=True)
            return True
        except (FileNotFoundError, subprocess.CalledProcessError):
            return False