import gradio as gr
import whisper
from moviepy.editor import VideoFileClip, AudioFileClip, ImageClip, CompositeVideoClip
import tempfile
import os
from pathlib import Path
import numpy as np
from PIL import Image, ImageDraw, ImageFont
import arabic_reshaper
from bidi.algorithm import get_display
from pydub import AudioSegment

# تحميل نموذج Whisper
model = whisper.load_model("base")  # نموذج أفضل للغة العربية

# تحديد الخطوط المتاحة
FONTS = {
    "الخط المثنى": "fonts/Al-Mothnna.ttf",
    "خط بين": "fonts/bein-normal.ttf"
}

def prepare_arabic_text(text):
    """تحضير النص العربي للعرض بشكل صحيح"""
    try:
        reshaped_text = arabic_reshaper.reshape(text)
        bidi_text = get_display(reshaped_text)
        return bidi_text
    except Exception as e:
        print(f"خطأ في معالجة النص العربي: {str(e)}")
        return text

def create_text_image(text, font_name, size=(720, 480), font_size=30):
    """إنشاء صورة تحتوي على نص"""
    # إنشاء صورة جديدة مع خلفية سوداء
    img = Image.new('RGB', size, 'black')
    draw = ImageDraw.Draw(img)
    
    # تحميل الخط المحدد
    try:
        font_path = FONTS[font_name]
        if not os.path.exists(font_path):
            raise FileNotFoundError(f"الخط غير موجود: {font_path}")
        font = ImageFont.truetype(font_path, font_size)
    except Exception as e:
        print(f"خطأ في تحميل الخط: {str(e)}")
        # استخدام الخط الافتراضي في حالة الفشل
        font = ImageFont.load_default()

    # تحضير النص العربي
    prepared_text = prepare_arabic_text(text)
    
    # حساب موقع النص في وسط الصورة
    text_bbox = draw.textbbox((0, 0), prepared_text, font=font)
    text_width = text_bbox[2] - text_bbox[0]
    text_height = text_bbox[3] - text_bbox[1]
    
    x = (size[0] - text_width) // 2
    y = (size[1] - text_height) // 2
    
    # رسم النص
    draw.text((x, y), prepared_text, font=font, fill='white')
    
    return np.array(img)

def convert_audio_to_wav(audio_path):
    """تحويل الملف الصوتي إلى صيغة WAV"""
    audio_path = Path(audio_path)
    if audio_path.suffix.lower() != '.wav':
        wav_path = audio_path.with_suffix('.wav')
        audio = AudioSegment.from_file(str(audio_path))
        audio.export(str(wav_path), format='wav')
        return str(wav_path)
    return str(audio_path)

def create_video_with_text(audio_path, transcription, font_name, video_size):
    """إنشاء فيديو مع نص متزامن"""
    try:
        # تحويل الملف الصوتي إلى WAV
        wav_path = convert_audio_to_wav(audio_path)
        
        # تحميل الملف الصوتي
        audio_clip = AudioFileClip(wav_path)
        duration = audio_clip.duration
        
        # تقسيم النص إلى أجزاء
        words = transcription.split()
        total_frames = int(duration * 24)  # 24 FPS
        words_per_frame = max(1, len(words) // total_frames)
        
        # إنشاء قائمة المقاطع
        clips = []
        current_time = 0
        frame_duration = duration / (len(words) / words_per_frame)
        
        for i in range(0, len(words), words_per_frame):
            # تجميع الكلمات لهذا الإطار
            frame_words = ' '.join(words[i:i + words_per_frame])
            
            # إنشاء صورة للنص
            text_image = create_text_image(frame_words, font_name, size=video_size)
            
            # تحويل الصورة إلى مقطع
            text_clip = ImageClip(text_image).set_duration(frame_duration)
            
            # إضافة المقطع مع توقيته
            clips.append(text_clip.set_start(current_time))
            current_time += frame_duration
        
        if not clips:
            raise ValueError("لم يتم إنشاء أي مقاطع")
        
        # دمج جميع المقاطع
        video = CompositeVideoClip(clips, size=video_size)
        video = video.set_audio(audio_clip)
        
        # حفظ الفيديو
        temp_output = tempfile.NamedTemporaryFile(delete=False, suffix='.mp4')
        video_path = temp_output.name
        
        video.write_videofile(
            video_path,
            fps=24,
            codec='libx264',
            audio_codec='aac',
            verbose=False
        )
        
        return video_path
        
    except Exception as e:
        print(f"خطأ في create_video_with_text: {str(e)}")
        raise

def process_audio(audio_path, selected_font, video_orientation):
    """معالجة الملف الصوتي وإنشاء الفيديو"""
    try:
        if not isinstance(audio_path, str):
            raise ValueError("يجب أن يكون المدخل مسار ملف صوتي")
            
        if not os.path.exists(audio_path):
            raise FileNotFoundError("الملف غير موجود")
        
        # تحويل الصوت إلى نص
        print("جاري تحويل الصوت إلى نص...")
        result = model.transcribe(audio_path, language="ar")  # تحديد اللغة العربية
        transcription = result["text"]
        print("تم استخراج النص بنجاح")
        
        # تحديد حجم الفيديو بناءً على الاختيار
        video_size = (1280, 720) if video_orientation == 'أفقي' else (720, 1280)
        
        # إنشاء الفيديو
        print("جاري إنشاء الفيديو...")
        video_path = create_video_with_text(audio_path, transcription, selected_font, video_size)
        print("تم إنشاء الفيديو بنجاح")
        
        return video_path, transcription
    except Exception as e:
        print(f"خطأ في process_audio: {str(e)}")
        return None, f"حدث خطأ أثناء المعالجة: {str(e)}"

# إنشاء واجهة Gradio
iface = gr.Interface(
    fn=process_audio,
    inputs=[
        gr.Audio(type="filepath", label="قم بتحميل ملف صوتي (MP3 أو WAV)"),
        gr.Dropdown(
            choices=list(FONTS.keys()),
            value=list(FONTS.keys())[0],
            label="اختر الخط"
        ),
        gr.Dropdown(
            choices=["أفقي", "عمودي"],
            value="أفقي",
            label="اختيار اتجاه الفيديو"
        )
    ],
    outputs=[
        gr.Video(label="الفيديو المنشأ"),
        gr.Textbox(label="النص المستخرج")
    ],
    title="محول الصوت إلى فيديو مع النص",
    description="قم بتحميل ملف صوتي لإنشاء فيديو مع نص متزامن باللغة العربية.",
)

if __name__ == "__main__":
    # التحقق من وجود مجلد الخطوط
    if not os.path.exists("fonts"):
        print("تحذير: مجلد الخطوط غير موجود")
        os.makedirs("fonts")
        
    # التحقق من وجود الخطوط
    for font_name, font_path in FONTS.items():
        if not os.path.exists(font_path):
            print(f"تحذير: الخط {font_name} غير موجود في {font_path}")
            
    iface.launch()