# helper_functions.py
from passlib.context import CryptContext
from gtts import gTTS
import io
import re
import os
import base64
import jwt
# import google.generativeai as genai # Still needed if you use Gemini in other helper functions
from io import BytesIO
from dotenv import load_dotenv
from fastapi import HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from datetime import datetime, timedelta
from typing import Optional
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

# Load environment variables (important for JWT_SECRET_KEY)
load_dotenv()

ALGORITHM = "HS256"
JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY")

async def generate_tts_audio(text: str, lang='en') -> bytes:
    """Generates speech audio data from text using gTTS."""

    # Updated mapping based on common gTTS language codes and your project's needs
    # Note: gTTS language codes are often 2-letter ISO 639-1, or sometimes with region like 'en-US', 'en-IN'
    # Ensure these match what gTTS expects and what you pass from the frontend.
    gtts_languages = {
        "english": "en",
        "hindi": "hi",
        "bengali": "bn",
        "tamil": "ta",
        "telugu": "te",
        "marathi": "mr",
        "gujarati": "gu",
        "kannada": "kn",
        "malayalam": "ml", # gTTS typically uses 'ml' for Malayalam
        "odia": "or",
        "punjabi": "pa",
        "assamese": "as",
        "urdu": "ur",
        "sanskrit": "sa"
    }

    try:
        # Use the specific gTTS language code, default to 'en' if not found
        gtts_lang_code = gtts_languages.get(lang.lower(), 'en')
        tts = gTTS(text=text, lang=gtts_lang_code, tld='us')
        buffer = BytesIO()
        tts.write_to_fp(buffer)
        buffer.seek(0)
        audio_data = buffer.read()
        return audio_data
    except Exception as e:
        print(f"Error generating TTS with gTTS for language '{lang}': {e}")
        return None

# --- These functions are no longer needed as Gemini handles the conversion ---
# async def convert_voice_to_text(audio_bytes: bytes, lang='en') -> str: ...
# def read_text_from_image(image_bytes: bytes) -> str: ...
# def read_text_from_pdf(pdf_bytes: bytes) -> str: ...

def extract_last_question(text):
    """Try to get the last question asked in the AI response."""
    questions = re.findall(r"[^?.!]*\?", text)
    return questions[-1].strip() if questions else ""

# Simplified detect_file_type - you might not even need this if you rely on frontend MIME type or magic numbers
# However, it's good to keep a basic check or rely on `python-magic` for more robust detection if needed.
# For this example, we'll assume the frontend provides a 'message_type' that matches file types.
def get_mime_type_from_file_bytes(file_bytes: bytes) -> Optional[str]:
    """
    Attempts to determine the MIME type of a file based on its magic bytes.
    This is a simplified version. For robust detection, consider 'python-magic'.
    """
    # PDF magic number
    if file_bytes.startswith(b'%PDF'):
        return "application/pdf"
    # Common image magic numbers
    elif file_bytes.startswith(b'\xFF\xD8\xFF'): # JPEG
        return "image/jpeg"
    elif file_bytes.startswith(b'\x89PNG\x0D\x0A\x1A\x0A'): # PNG
        return "image/png"
    elif file_bytes.startswith(b'GIF87a') or file_bytes.startswith(b'GIF89a'): # GIF
        return "image/gif"
    # Common audio magic numbers (simplified, more robust detection for audio is complex)
    # MP3 (ID3 tag at start or common headers)
    elif file_bytes.startswith(b'ID3') or (len(file_bytes) > 2 and file_bytes[0] == 0xFF and (file_bytes[1] & 0xF0) == 0xF0):
        return "audio/mpeg" # For MP3
    # WAV (RIFF header)
    elif file_bytes.startswith(b'RIFF') and file_bytes[8:12] == b'WAVE':
        return "audio/wav"
    # OGG (Opus, Vorbis, FLAC in Ogg container)
    elif file_bytes.startswith(b'OggS'):
        # This is generic Ogg. For specific audio types like opus, vorbis, you'd need deeper parsing.
        # For simplicity, we'll use audio/ogg. Gemini typically handles these if it recognizes the codec.
        return "audio/ogg"
    # WEBM (EBM/Matroska container)
    elif file_bytes.startswith(b'\x1a\x45\xdf\xa3'):
        return "video/webm" # Often contains audio/video
    # FLAC (fLaC header)
    elif file_bytes.startswith(b'fLaC'):
        return "audio/flac"
    return None # Unknown or unsupported type

def extract_current_topic(text):
    # Simple example: look for capitalized words after "Topic:"
    match = re.search(r"(?:Topic|Lesson|Chapter|Unit)\s*[:\-–]?\s*(.+)", text)
    if match:
        return match.group(1).strip()
    else:
        return "General"  # Default topic


# def is_answer_correct(text):
#     # Simple check: look for phrases like "Great job!", "Correct!"
#     if re.search(r"Great job|Correct", text, re.IGNORECASE):
#         return True
#     elif re.search(r"incorrect|wrong", text, re.IGNORECASE):
#         return False
#     return False


def detect_file_type(file_bytes: bytes) -> str:
    if file_bytes.startswith(b'%PDF'):
        return "application/pdf"
    elif file_bytes[0:4] == b"\xFF\xD8\xFF\xE0":
        return "image/jpeg"
    elif file_bytes[0:4] == b"\x89PNG":
        return "image/png"
    elif file_bytes.startswith(b'RIFF') and file_bytes[8:12] == b'WAVE':
        return "audio/wav"
    else:
        return "unknown"  # Default for unsupported types
        
# def is_answer_correct(text):
#     """
#     Detects whether the student's answer was correct or incorrect
#     based on specific keywords in the Gemini response.
    
#     Args:
#         text (str): The response from Gemini
        
#     Returns:
#         bool: True if correct, False if incorrect
#     """
    
#     # Keywords for correct answers
#     correct_keywords = [
#         'correct', 'excellent', 'perfect', 'wonderful', 
#         'amazing', 'brilliant', 'outstanding', 'right'
#     ]
    
#     # Keywords for incorrect answers
#     incorrect_keywords = [
#         'incorrect', 'wrong', 'mistaken', 'sorry', 'oops', 'actually'
#     ]
    
#     # Convert to lowercase for case-insensitive matching
#     text_lower = text.lower()
    
#     # Get first 20 words to check for keywords (they should be at the start)
#     first_words = ' '.join(text_lower.split()[:20])
    
#     # Check for correct keywords
#     for keyword in correct_keywords:
#         if keyword in first_words:
#             return True
    
#     # Check for incorrect keywords
#     for keyword in incorrect_keywords:
#         if keyword in first_words:
#             return False
    
#     # Default to False if no keywords found (safer approach)
#     return None



def is_answer_correct(text):
    """
    Detects whether the student's answer was correct or incorrect
    based on specific keywords in the Gemini response.
    
    Args:
        text (str): The response from Gemini
        
    Returns:
        bool: True if correct, False if incorrect
    """
    
    # Keywords for correct answers
    # correct_keywords = [
    #     'correct', 'excellent', 'perfect', 'wonderful', 
    #     'amazing', 'brilliant', 'outstanding', 'right', 'सही'
    # ]
    correct_keywords = [
    # English
    "correct", "excellent", "perfect", "wonderful",
    "amazing", "brilliant", "outstanding", "exactly",

    # Hindi
    "सही", "उत्कृष्ट", "परफेक्ट", "शानदार",
    "कमाल", "प्रखर", "बिल्कुल",

    # Telugu
    "సరైనది", "అద్భుతం", "పర్ఫెక్ట్", "అద్భుతమైన",
    "అమేజింగ్", "మెరుగైన", "అత్యుత్తమం", "ఖచ్చితంగా",

    # Bengali
    "সঠিক", "চমৎকার", "পারফেক্ট", "দারুণ",
    "অসাধারণ", "উজ্জ্বল", "অতি উত্তম", "ঠিকই",

    # Tamil
    "சரியானது", "அற்புதம்", "பர்பெக்ட்", "அழகானது",
    "ஆச்சரியம்", "தீட்டமான", "சிறந்தது", "சரியாக",

    # Marathi
    "बरोबर", "उत्कृष्ट", "परफेक्ट", "छान",
    "आश्चर्यकारक", "तेजस्वी", "उत्कृष्ट कामगिरी", "बिल्कुल",

    # Gujarati
    "સારું", "ઉત્કૃષ્ટ", "પરફેક્ટ", "અદભૂત",
    "કમાલ", "બ્રિલિયન્ટ", "ઉત્તમ", "બિલકુલ",

    # Kannada
    "ಸರಿಯಾದ", "ಅತ್ಯುತ್ತಮ", "ಪರಿಪೂರ್ಣ", "ಅದ್ಭುತ",
    "ಆಶ್ಚರ್ಯಕರ", "ಪ್ರತಿಭಾಶಾಲಿ", "ಅತ್ಯುತ್ತಮವಾದ", "ಖಚಿತವಾಗಿ",

    # Malayalam
    "ശരി", "അത്യുത്തരം", "പർഫെക്ട്", "അദ്ഭുതം",
    "വിസ്മയം", "പ്രതിഭ", "ഏറ്റവും മികച്ചത്", "തികച്ചും",

    # Odia
    "ଠିକ", "ଉତ୍କୃଷ୍ଟ", "ପର୍ଫେକ୍ଟ", "ଦରୁଣ",
    "ଆଶ୍ଚର୍ଯ୍ୟଜନକ", "ଦୀପ୍ତିମାନ", "ଆଶାଧାରଣ", "ଠିକ୍ ଠିକ୍",

    # Punjabi
    "ਸਹੀ", "ਉਤਕ੍ਰਿਸ਼ਟ", "ਪਰਫੈਕਟ", "ਸ਼ਾਨਦਾਰ",
    "ਕਮਾਲ", "ਬ੍ਰਿਲੀਅੰਟ", "ਵਧੀਆ", "ਬਿਲਕੁਲ",

    # Assamese
    "ঠিক", "অতি উৎকৃষ্ট", "পৰফেক্ট", "দৰ্শনীয়",
    "অবিশ্বাস্য", "উজ্জ্বল", "শ্ৰেষ্ঠ", "ঠিককৈ",

    # Urdu
    "درست", "بہت خوب", "بہترین", "شاندار",
    "حیرت انگیز", "عمدہ", "بہترین کارکردگی", "بالکل",

    # Sanskrit
    "सम्यक्", "उत्कृष्टम्", "परिपूर्णम्", "अद्भुतम्",
    "आश्चर्यजनकम्", "दीप्तिमान्", "श्रेष्ठम्", "निश्चयेन"
    ]


    # Keywords for incorrect answers
    # incorrect_keywords = [
    #     'incorrect', 'wrong', 'mistaken', 'sorry', 'oops', 'actually', 'नहीं'
    # ]
    incorrect_keywords = [
    # English
    "incorrect", "wrong", "mistaken", "sorry", "oops", "actually",

    # Hindi
    "गलत", "त्रुटि", "भूल", "माफ़ करना", "ओह", "दरअसल",

    # Telugu
    "తప్పు", "తప్పుగా", "తప్పిదం", "క్షమించండి", "ఓహ్", "నిజానికి",

    # Bengali
    "ভুল", "অসম্পূর্ণ", "ভ্রান্ত", "দুঃখিত", "ওহ", "আসলে",

    # Tamil
    "தவறு", "தவறானது", "பிழை", "மன்னிக்கவும்", "ஓஹ்", "உண்மையில்",

    # Marathi
    "चूक", "गैर", "चुकीचे", "माफ करा", "अरेरे", "खरं तर",

    # Gujarati
    "ખોટું", "ભૂલ", "ખરાબ", "માફ કરશો", "ઓહ", "અસલમાં",

    # Kannada
    "ತಪ್ಪು", "ತಪ್ಪಾಗಿದೆ", "ತಪ್ಪಾಗಿ", "ಕ್ಷಮಿಸಿ", "ಅಯ್ಯೋ", "ವಾಸ್ತವವಾಗಿ",

    # Malayalam
    "തെറ്റാണ്", "തെറ്റ്", "തെറ്റിദ്ധരിച്ചത്", "ക്ഷമിക്കണം", "ഓഹ്", "വാസ്തവത്തിൽ",

    # Odia
    "ଭୁଲ", "ତ୍ରୁଟି", "ଭ୍ରମ", "ମାଫ କରନ୍ତୁ", "ଓହ୍", "ବାସ୍ତବରେ",

    # Punjabi
    "ਗਲਤ", "ਭੁੱਲ", "ਖਰਾਬ", "ਮਾਫ਼ ਕਰਨਾ", "ਓਹ", "ਅਸਲ ਵਿੱਚ",

    # Assamese
    "ভুল", "অশুদ্ধ", "বিকৃত", "ক্ষমা কৰা", "অ’", "আসলতে",

    # Urdu
    "غلط", "خطا", "غلطی", "معاف کرنا", "اوہ", "اصل میں",

    # Sanskrit
    "असम्यक्", "अयुक्तम्", "भ्रान्तिः", "क्षम्यताम्", "हाय्", "वास्तुतः"
    ]

    # Convert to lowercase for case-insensitive matching
    text_lower = text.lower()
    
    # Get first 20 words to check for keywords (they should be at the start)
    first_words = ' '.join(text_lower.split()[:20])
    
    # Check for correct keywords
    for keyword in correct_keywords:
        if keyword in first_words:
            return True
    
    # Check for incorrect keywords
    for keyword in incorrect_keywords:
        if keyword in first_words:
            return False
    
    # Default to False if no keywords found (safer approach)
    return None
