import requests
import json
import base64
import os
from google.oauth2 import service_account
from google.auth.transport.requests import Request as AuthRequest

# --- Global Configuration ---
# IMPORTANT: Replace this with the actual path to your downloaded JSON key file.
KEY_FILE_PATH = "TTS_SERVICE.json" 
SCOPE = ["https://www.googleapis.com/auth/cloud-platform"] 
API_ENDPOINT = "https://texttospeech.googleapis.com/v1/text:synthesize"

# --- Utility Function: Authentication ---

def get_authenticated_token(key_file_path, scopes):
    """
    Loads the service account credentials and generates a short-lived access token.
    The token is required for calling the Google Cloud TTS API.
    """
    try:
        # Load credentials from the service account file
        credentials = service_account.Credentials.from_service_account_file(
            key_file_path,
            scopes=scopes
        )
        
        # Force a token refresh (necessary for initial token acquisition)
        credentials.refresh(AuthRequest())
        
        return credentials.token
    except Exception as e:
        # This error is usually due to a wrong file path or missing IAM permissions
        print(f"Authentication Error: Could not load key file or generate token: {e}")
        print(f"Please check if the KEY_FILE_PATH is correct: {key_file_path}")
        return None

# --- Core Function: Speech Synthesis (Refactored for Reusability) ---
LANGUAGE_VOICE_MAP = {
        # Frontend Value : [Language Code, Voice Name (Male Wavenet/Neural2)]
        "english":    ["en-US", "en-US-Journey-"], # Journey
        "hindi":      ["hi-IN", "hi-IN-Wavenet-"], # Male, India
        "telugu":     ["te-IN", "te-IN-Standard-"], # Male, India
        "bengali":    ["bn-IN", "bn-IN-Standard-"], # Male, India
        "tamil":      ["ta-IN", "ta-IN-Standard-"], # Male, India
        "marathi":    ["mr-IN", "mr-IN-Standard-"], # Male, India
        "gujarati":   ["gu-IN", "gu-IN-Standard-"], # Male, India
        "kannada":    ["kn-IN", "kn-IN-Standard-"], # Male, India
        "malayalam":  ["ml-IN", "ml-IN-Chirp3-HD-"], # Male, India
        "odia":       ["or-IN", "or-IN-Standard-"], # Male, India
        # Note: Punjabi, Assamese, Urdu, and Sanskrit currently do not have dedicated 
        # Wavenet/Neural2 voices in the hi-IN region. You may need to use a Standard voice 
        # or another regional voice if one exists and supports the script.
        "punjabi":    ["pa-IN", "pa-IN-Standard-"], # Male Standard voice
        "assamese":   ["as-IN", "as-IN-Standard-"], # Male Standard voice
        "urdu":       ["ur-IN", "ur-IN-Wavenet-"], # Male Standard voice (Pakistan region)
        "sanskrit":   ["sa-IN", "sa-IN-Standard-"], # Male Standard voice
    }

VOICES = {
    "male": "D",
    "female": "F"
          }
VOICE_URDU = {
    "male": "B",
    "female": "A"
}
VOICE_MALAYALAM = {
    "male": "Sadachbia",
    "female": "Leda"
}
          

def generate_tts_base64_audio(text_to_speak, voice_name, language='english'):
    """
    Calls the Google Cloud TTS API to generate speech and returns 
    the Base64 encoded audio string.
    
    Args:
        text_to_speak (str): The text content to be synthesized.
        voice_name (str): The specific voice model name (e.g., "en-US-Wavenet-F").
        
    Returns:
        str or None: The Base64 encoded audio content string, or None on failure.
    """
    if language == "urdu":
        gender = VOICE_URDU.get(voice_name, "B")
    elif language == "malayalam":
        gender = VOICE_MALAYALAM.get(voice_name, "Sadachbia")
    else:
        gender = VOICES.get(voice_name, "D")
    
    voice_name = LANGUAGE_VOICE_MAP.get(language, LANGUAGE_VOICE_MAP["english"])[1]+ gender
    print(f"Using voice: {voice_name} for language: {language}")
    # 1. Get the access token
    token = get_authenticated_token(KEY_FILE_PATH, SCOPE)
    if not token:
        return None # Failed to authenticate

    # 2. Construct the API request body dynamically
    #voice_name = "en-IN-Standard-F"
    
    request_data = {
        "input": {
            "text": text_to_speak
        },
        "voice": {
            "languageCode": voice_name[:5], # e.g., "en-US-Wavenet-F" -> "en-US"
            "name": voice_name 
        },
        "audioConfig": {
            "audioEncoding": "MP3"
        }
    }

    # 3. Define the request headers
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json; charset=utf-8"
    }

    print(f"Synthesizing text with voice '{voice_name}'...")

    try:
        # 4. Send the POST request
        response = requests.post(API_ENDPOINT, headers=headers, data=json.dumps(request_data))
        response.raise_for_status() # Raises an HTTPError for bad responses (4xx or 5xx)

        response_json = response.json()
        
        # 5. Extract and return the Base64 audio content
        if 'audioContent' in response_json:
            print("Synthesis successful. Returning Base64 audio string.")
            return response_json['audioContent']
        else:
            print("ERROR: Successful response but missing 'audioContent'.")
            return None

    except requests.exceptions.HTTPError as errh:
        print("-" * 50)
        print("HTTP Error occurred (TTS API call failed):")
        try:
            error_details = response.json()
            print("Error Details:", json.dumps(error_details, indent=2))
        except json.JSONDecodeError:
            print("Could not decode error response body as JSON.")
            print("Response Text:", response.text)
        print("-" * 50)
        return None
    except requests.exceptions.RequestException as err:
        print(f"A connection error occurred: {err}")
        return None
    except Exception as e:
        print(f"An unexpected error occurred: {e}")
        return None


# --- Example Usage (Main Execution Block) ---

if __name__ == "__main__":
    
    # Define a dictionary of common voices for easy selection
    VOICES = {
        "male_wavenet": "en-US-Wavenet-D",  # Male voice
        "female_wavenet": "en-US-Wavenet-F", # Female voice
        "male_standard": "en-US-Standard-D",
        "female_standard": "en-US-Standard-F",
        "custom_wavenet": "en-US-Wavenet-H" # A different female voice
    }

    test_text = "This is a test of the new function. The voice will be converted into a Base64 string for the front-end to use."
    
    # --- Test Case 1: Female Voice ---
    print("\n" + "=" * 50)
    print("TEST CASE 1: FEMALE VOICE")
    print("=" * 50)
    
    base64_audio_female = generate_tts_base64_audio(
        text_to_speak=test_text,
        voice_name=VOICES["female_wavenet"]
    )

    if base64_audio_female:
        print(f"\nBase64 Audio (Female, first 50 chars): {base64_audio_female[:50]}...")
        
        # OPTIONAL: Decode and save the file to verify it worked (Backend only)
        with open("female_audio.mp3", "wb") as f:
            f.write(base64.b64decode(base64_audio_female))
        print(f"Successfully saved test file: {os.path.abspath('female_audio.mp3')}")

    # --- Test Case 2: Male Voice ---
    print("\n" + "=" * 50)
    print("TEST CASE 2: MALE VOICE")
    print("=" * 50)
    
    base64_audio_male = generate_tts_base64_audio(
        text_to_speak="A quick message using a male voice.",
        voice_name=VOICES["male_wavenet"]
    )

    if base64_audio_male:
        print(f"\nBase64 Audio (Male, first 50 chars): {base64_audio_male[:50]}...")
        
        # OPTIONAL: Decode and save the file to verify it worked (Backend only)
        with open("male_audio.mp3", "wb") as f:
            f.write(base64.b64decode(base64_audio_male))
        print(f"Successfully saved test file: {os.path.abspath('male_audio.mp3')}")
    else:
        print("Male voice synthesis failed.")