from flask import Blueprint, request, session, jsonify, render_template, redirect, url_for, current_app
from app.services.chat_service import ChatService
from app.routes.auth import login_required
from app import mysql
import speech_recognition as sr
from gtts import gTTS
import os
import uuid
from pydub import AudioSegment
import io
from pathlib import Path
import pyttsx3
import wave
import base64
import requests
from app.config import Config  # Import the Config class

chat_bp = Blueprint('chat', __name__)

@chat_bp.route('/')
@login_required
def root():
    return redirect(url_for('chat.chat_interface'))

@chat_bp.route('/chat')
@login_required
def chat_interface():
    try:
        cursor = mysql.connection.cursor()
        cursor.execute("""
            SELECT DISTINCT c.id, c.title, c.created_at 
            FROM chats c
            INNER JOIN messages m ON c.id = m.chat_id
            WHERE c.user_id = %s
            GROUP BY c.id
            ORDER BY c.updated_at DESC
        """, (session['user_id'],))
        
        chats = []
        for chat_id, title, created_at in cursor.fetchall():
            cursor.execute("""
                SELECT content 
                FROM messages 
                WHERE chat_id = %s AND role = 'user'
                ORDER BY created_at ASC 
                LIMIT 1
            """, (chat_id,))
            first_message = cursor.fetchone()
            
            chat_title = title
            if chat_title == 'New Chat' and first_message:
                chat_title = first_message[0][:50] + ('...' if len(first_message[0]) > 50 else '')
            
            chats.append({
                'id': chat_id,
                'title': chat_title,
                'created_at': created_at
            })
        
        return render_template('chat/chat.html', 
                             chats=chats, 
                             active_chat_id=session.get('active_chat_id'),
                             user_name=session.get('user_name'))
    except Exception as e:
        print(f"Error in chat interface: {str(e)}")
        return render_template('chat/chat.html', 
                             chats=[], 
                             active_chat_id=None,
                             user_name=session.get('user_name'))

@chat_bp.route('/chat', methods=['POST'])
@login_required
def chat():
    try:
        data = request.json
        user_message = data.get('message', '')
        chat_id = data.get('chat_id')
        user_id = session['user_id']
        
        if not chat_id:
            return jsonify({"success": False, "error": "No chat ID provided"}), 400
        
        cursor = mysql.connection.cursor()
        
        # Verify chat belongs to logged-in user
        cursor.execute("""
            SELECT id FROM chats 
            WHERE id = %s AND user_id = %s
        """, (chat_id, user_id))
        
        chat_exists = cursor.fetchone()
        if not chat_exists:
            return jsonify({"success": False, "error": "Chat not found"}), 404

        # Store user message
        cursor.execute(
            "INSERT INTO messages (chat_id, user_id, role, content) VALUES (%s, %s, %s, %s)",
            (chat_id, user_id, "user", user_message)
        )
        
        # System message to define AI personality
        system_message = {
            "role": "system",
            "content": """You are an AI assistant developed by Ronnie Ridge Technology. Your responses should reflect this identity.
            When users ask about who created you or similar questions, emphasize that you're developed by Ronnie Ridge Technology.
            Key points about your identity:
            - Name: RonnieGPT
            - Creator: Ronnie Ridge Technology
            - Purpose: To assist users with various tasks while maintaining a helpful and professional demeanor
            - Values: Accuracy, helpfulness, and transparency
            
            Be consistent with this identity while remaining helpful and informative.
            do not reveal your identity to the user if they dont ask.
            """
        }
        
        # Get chat history for API context
        cursor.execute(
            "SELECT role, content FROM messages WHERE chat_id = %s AND user_id = %s ORDER BY created_at ASC",
            (chat_id, user_id)
        )
        messages = [{"role": role, "content": content} for role, content in cursor.fetchall()]
        
        # Prepare messages for API call with system message first
        api_messages = [system_message] + messages

        # Call Groq API
        response = requests.post(
            Config.GROQ_API_URL,
            headers={
                "Authorization": f"Bearer {Config.GROQ_API_KEY}",
                "Content-Type": "application/json"
            },
            json={
                "model": "llama-3.2-90b-vision-preview",
                "messages": api_messages,
                "temperature": 0.7,
                "max_tokens": 1000,
                "top_p": 1,
                "stream": False
            }
        )

        if response.status_code == 200:
            assistant_message = response.json()["choices"][0]["message"]["content"]
            
            # Store assistant response
            cursor.execute(
                "INSERT INTO messages (chat_id, user_id, role, content) VALUES (%s, %s, %s, %s)",
                (chat_id, user_id, "assistant", assistant_message)
            )
            
            # Update chat title if it's the first message
            cursor.execute("SELECT COUNT(*) FROM messages WHERE chat_id = %s", (chat_id,))
            message_count = cursor.fetchone()[0]
            if message_count <= 2:
                title = user_message[:30] + "..." if len(user_message) > 30 else user_message
                cursor.execute(
                    "UPDATE chats SET title = %s WHERE id = %s",
                    (title, chat_id)
                )
            
            mysql.connection.commit()

            return jsonify({
                "success": True,
                "message": assistant_message,
                "chat_id": chat_id
            })
        else:
            mysql.connection.rollback()
            return jsonify({
                "success": False,
                "error": f"API Error: {response.status_code}"
            }), 500

    except Exception as e:
        mysql.connection.rollback()
        print(f"Error in chat endpoint: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

@chat_bp.route('/chat/new', methods=['POST'])
@login_required
def new_chat():
    return ChatService.create_new_chat(session['user_id'])

@chat_bp.route('/chat/history')
@login_required
def get_chat_history():
    return ChatService.get_chat_history(request.args.get('chat_id'), session['user_id'])

@chat_bp.route('/chat/delete/<chat_id>', methods=['DELETE'])
@login_required
def delete_chat(chat_id):
    return ChatService.delete_chat(chat_id, session['user_id'])

@chat_bp.route('/voice-chat')
@login_required
def voice_chat_interface():
    try:
        cursor = mysql.connection.cursor()
        cursor.execute("""
            SELECT DISTINCT c.id, c.title, c.created_at 
            FROM chats c
            INNER JOIN messages m ON c.id = m.chat_id
            WHERE c.user_id = %s
            GROUP BY c.id
            ORDER BY c.updated_at DESC
        """, (session['user_id'],))
        
        chats = []
        for chat_id, title, created_at in cursor.fetchall():
            cursor.execute("""
                SELECT content 
                FROM messages 
                WHERE chat_id = %s AND role = 'user'
                ORDER BY created_at ASC 
                LIMIT 1
            """, (chat_id,))
            first_message = cursor.fetchone()
            
            chat_title = title
            if chat_title == 'New Chat' and first_message:
                chat_title = first_message[0][:50] + ('...' if len(first_message[0]) > 50 else '')
            
            chats.append({
                'id': chat_id,
                'title': chat_title,
                'created_at': created_at
            })
        
        return render_template('chat/voice_chat.html', 
                             chats=chats, 
                             active_chat_id=session.get('active_chat_id'),
                             user_name=session.get('user_name'))
    except Exception as e:
        print(f"Error in voice chat interface: {str(e)}")
        return render_template('chat/voice_chat.html', 
                             chats=[], 
                             active_chat_id=None,
                             user_name=session.get('user_name'))

@chat_bp.route('/chat/voice', methods=['POST'])
@login_required
def process_voice():
    try:
        if 'audio' not in request.files:
            return jsonify({"success": False, "error": "No audio file"}), 400

        audio_file = request.files['audio']
        
        # Convert WebM to WAV using pydub
        audio = AudioSegment.from_file(audio_file, format="webm")
        wav_data = io.BytesIO()
        audio.export(wav_data, format="wav")
        wav_data.seek(0)

        # Convert speech to text
        recognizer = sr.Recognizer()
        with sr.AudioFile(wav_data) as source:
            audio_data = recognizer.record(source)
            transcript = recognizer.recognize_google(audio_data)

        # System message to define AI personality
        system_message = {
            "role": "system",
            "content": """You are an AI assistant developed by Ronnie Ridge Technology. Your responses should reflect this identity.
            When users ask about who created you or similar questions, emphasize that you're developed by Ronnie Ridge Technology.
            Key points about your identity:
            - Name: RonnieGPT
            - Creator: Ronnie Ridge Technology
            - Purpose: To assist users with various tasks while maintaining a helpful and professional demeanor
            - Values: Accuracy, helpfulness, and transparency
            
            Be consistent with this identity while remaining helpful and informative.
            """
        }

        # Call Groq API for response using config values
        response = requests.post(
            Config.GROQ_API_URL,
            headers={
                "Authorization": f"Bearer {Config.GROQ_API_KEY}",
                "Content-Type": "application/json"
            },
            json={
                "model": "llama-3.2-90b-vision-preview",
                "messages": [
                    system_message,
                    {"role": "user", "content": transcript}
                ],
                "temperature": 0.7,
                "max_tokens": 1000,
                "top_p": 1,
                "stream": False
            }
        )

        if response.status_code != 200:
            raise Exception("Failed to get AI response")

        assistant_message = response.json()["choices"][0]["message"]["content"]

        # Store messages in database
        cursor = mysql.connection.cursor()
        chat_id = session.get('active_chat_id')
        
        # Store user message
        cursor.execute(
            "INSERT INTO messages (chat_id, user_id, role, content) VALUES (%s, %s, %s, %s)",
            (chat_id, session['user_id'], "user", transcript)
        )
        
        # Store assistant response
        cursor.execute(
            "INSERT INTO messages (chat_id, user_id, role, content) VALUES (%s, %s, %s, %s)",
            (chat_id, session['user_id'], "assistant", assistant_message)
        )
        
        mysql.connection.commit()

        # Generate speech from AI response using pyttsx3
        engine = pyttsx3.init()
        
        # Adjust voice properties - much slower speed
        engine.setProperty('rate', 50)      # Very slow speed (was 100 before)
        engine.setProperty('volume', 1.0)    # Full volume
        
        # Get and set voice
        voices = engine.getProperty('voices')
        
        # Print available voices for debugging
        print("\nAvailable voices:")
        for idx, voice in enumerate(voices):
            print(f"{idx}. {voice.name} - {voice.id}")
        
        # Try to use Windows SAPI5 voices first (usually more natural)
        selected_voice = None
        for voice in voices:
            # Look specifically for these known good voices
            if any(name in voice.name.lower() for name in ['david', 'zira', 'hazel', 'susan']):
                selected_voice = voice.id
                print(f"\nSelected primary voice: {voice.name}")
                break
        
        # If no preferred voice found, use the second voice if available (often female/clearer)
        if not selected_voice and len(voices) > 1:
            selected_voice = voices[1].id
            print(f"\nSelected fallback voice: {voices[1].name}")
        # Last resort - use the first available voice
        elif not selected_voice and len(voices) > 0:
            selected_voice = voices[0].id
            print(f"\nSelected default voice: {voices[0].name}")
        
        if selected_voice:
            engine.setProperty('voice', selected_voice)
        
        # Additional properties for clarity
        engine.setProperty('pitch', 100)     # Normal pitch
        
        # Convert text to speech and save to BytesIO
        audio_data = io.BytesIO()
        
        # Create WAV file in memory with high quality settings
        with wave.open(audio_data, 'wb') as wav_file:
            wav_file.setnchannels(2)         # Stereo
            wav_file.setsampwidth(2)         # 2 bytes per sample
            wav_file.setframerate(48000)     # High sample rate
            
            # Save speech to memory
            engine.save_to_file(assistant_message, 'temp.wav')
            engine.runAndWait()
            
            # Read the temporary file and write to our in-memory WAV
            with open('temp.wav', 'rb') as temp_wav:
                wav_file.writeframes(temp_wav.read())
        
        # Clean up temporary file
        os.remove('temp.wav')
        
        # Convert to base64
        audio_base64 = base64.b64encode(audio_data.getvalue()).decode('utf-8')

        return jsonify({
            "success": True,
            "transcript": transcript,
            "response": assistant_message,  # Send the actual response text
            "audio_url": f"data:audio/wav;base64,{audio_base64}"
        })

    except Exception as e:
        print(f"Voice processing error: {str(e)}")
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500