# ========================================================================
# 📄 1 TOPICE GENERATE TEXT.py
# 🛠️ توليد النصوص باستخدام Google Generative AI مع توليد العنوان والوصف والكلمات الدلالية
# ========================================================================

import sys
sys.stdout.reconfigure(encoding='utf-8')
import os
import logging
import random
import re
import difflib
from num2words import num2words
import google.generativeai as genai

# =========================
# 🔧 إعداد المسارات المركزية
# =========================
# تحديد المسار الأساسي للمشروع
BASE_PATH = os.path.abspath("D:/YouTubeGen Pro 3")
CONFIG_PATH = os.path.join(BASE_PATH, "CONFIG")
OUTPUT_PATH = os.path.join(BASE_PATH, "OUTPUT", "Pro Output Text")  # المجلد المطلوب
LOGS_PATH = os.path.join(BASE_PATH, "LOGS")  # مجلد اللوجات الجديد

# إضافة CONFIG إلى مسارات البحث
if CONFIG_PATH not in sys.path:
    sys.path.append(CONFIG_PATH)

from config import load_api_keys, load_settings

# إنشاء مجلد الإخراج إذا لم يكن موجودًا
os.makedirs(OUTPUT_PATH, exist_ok=True)

# استدعاء إعدادات المشروع
# =========================
# 🔧 إعداد السجل
# =========================
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler(os.path.join(LOGS_PATH, 'generation.log'), encoding='utf-8'),  # ملف اللوج الجديد
        logging.StreamHandler(sys.stdout)  # مخرجات الشاشة مع الترميز الصحيح
    ]
)

# ========================================================================
# 🛠️ الوظائف المساعدة
# ========================================================================
def generate_text(api_key, prompt, max_words="10000", style="رسمى", text_type="مقال", excluded_keywords=None):
    """
    توليد النصوص باستخدام Google Generative AI مع استبعاد الكلمات الرئيسية المحددة.
    """
    genai.configure(api_key=api_key)
    try:
        model = genai.GenerativeModel('gemini-1.5-flash')
        chat = model.start_chat(history=[])

        # إضافة الكلمات الرئيسية المستبعدة إلى البرومبت
        excluded_prompt = ""
        if excluded_keywords:
            excluded_prompt = f"\n\nاستبعد تمامًا الكلمات الرئيسية التالية من النص: {', '.join(excluded_keywords)}."

        prompt_custom = f"""
        Generate a {style} {text_type} with approximately {max_words} words.

Start with a short and interesting introduction that grabs the reader's attention.

Welcome the readers and encourage them to follow the article until the end.

Ask them to subscribe to the channel and activate the bell button to receive all new updates.

The content must be:
1. Accurate and verifiable
2. If the topic is in Arabic, write all numbers in Arabic letters (e.g., "خمسة" instead of "5").
   If the topic is in English, write all numbers in English words (e.g., "five" instead of "5").

Strict restrictions on content:
- No religious content at all
- No discussion of prophets/messengers
- No content about any religions or beliefs
- No religious texts or references
- No spiritual or theological topics
- No discussion of divine/heavenly messages
- No religious historical events
- No topics without reliable sources or references

{excluded_prompt}

        Topic: {prompt}
        """
        logging.info(f"🔄 إرسال البرومبت: {prompt_custom}")
        response = chat.send_message(prompt_custom)

        if response.text:
            logging.info("✅ النص تم توليده بنجاح!")
            return response.text
        else:
            raise ValueError("⚠️ لم يتم توليد نص من النموذج.")
    except Exception as e:
        logging.error(f"❌ خطأ أثناء توليد النص: {e}")
        raise RuntimeError(f"⚠️ خطأ أثناء توليد النص: {e}")

def save_text_to_file(text, filename):
    """
    حفظ النصوص المُولدة إلى ملفات
    """
    try:
        file_path = os.path.join(OUTPUT_PATH, filename)
        with open(file_path, "w", encoding="utf-8") as f:
            f.write(text)
        logging.info(f"✅ تم حفظ الملف: {file_path}")
    except Exception as e:
        logging.error(f"❌ خطأ أثناء حفظ الملف: {e}")

def clean_and_format_text(input_text):
    """
    تنظيف النص وتنسيقه وإضافة تحسينات
    """
    logging.info("🔄 بدء تنظيف النص...")

    cleaned_line = re.sub(r"[\*\-\:\"\(\)\_\[\]\{\}\<\>\#]", "", input_text.strip())
    cleaned_line = re.sub(r"\s+", " ", cleaned_line)
    cleaned_line = re.sub(r'\d+', lambda x: num2words(int(x.group()), lang='ar'), cleaned_line)
    sentences = re.split(r"(?<!\w\.\w.)(?<![A-Z][a-z]\.)(?<=\.|\?)\s", cleaned_line)

    formatted_text = [sentence.strip() for sentence in sentences if sentence]

    if len(" ".join(formatted_text)) > 1000:
        intro = " "
        outro = "أَتْمَنَّىٰ أَنْ يَكُونَ ٱلْفِيدْيُو قَدْ نَالَ إِعْجَابَكُمْ."
    else:
        intro = " "
        outro = ""

    logging.info("✅ تم تنظيف النص بنجاح.")
    return f"{intro}\n\n{' '.join(formatted_text)}\n\n{outro}".strip()

# ========================================================================
# 🛠️ وظائف توليد العنوان والوصف والكلمات الدلالية
# ========================================================================
def generate_video_title(api_key, topic, topic_name):
    """
    توليد عنوان فيديو جذاب مع الهاشتاجات
    """
    prompt = (
        f"Generate a creative and engaging video title in Arabic for the topic '{topic}'. "
        f"The title should include the main name '{topic_name}' and express the essence of the topic in a unique way. "
        "It should be concise, full of curiosity, and include 3 trending Arabic hashtags relevant to the topic. "
        "Output only the generated title, without any additional text or labels."
    )
    return generate_text(api_key, prompt, max_words=10, style='جذاب', text_type='عنوان')

def generate_video_description(api_key, topic, cleaned_text):
    """
    توليد وصف الفيديو مع الهاشتاجات
    """
    prompt = (
        f"Create a highly engaging and SEO-optimized YouTube video description in Arabic for the topic '{topic}'. "
        f"Use the following content as a reference:\n\n{cleaned_text}\n\n"
        "The description should be concise, informative, and compelling to encourage viewers to watch the entire video. "
        "Include 30 trending hashtags relevant to the topic to maximize reach and engagement. "
        "Focus on making the description stand out in search results and suggested videos. "
        "Do not include phrases like 'وصف الفيديو' or 'وصف' in the output."
    )
    return generate_text(api_key, prompt, max_words=200, style='مفصل', text_type='وصف فيديو')

def generate_seo_keywords(api_key, topic):
    """
    توليد كلمات دلالية SEO مُحسّنة لليوتيوب
    """
    prompt = (
        f"Generate a highly optimized list of SEO keywords in Arabic for the topic '{topic}'. "
        "The keywords should be specifically tailored for YouTube search to maximize video visibility and ranking. "
        "Ensure the keywords are relevant, trending, and cover a wide range of related subtopics. "
        "The keywords must be separated strictly by commas (`,`). "
        "Do not exceed 350 characters in total. "
        "Avoid generic or unrelated keywords."
    )
    return generate_text(api_key, prompt, max_words=30, style='مباشر', text_type='كلمات دلالية')

# ========================================================================
# 🛠️ دوال تعديل النصوص بعد توليدها
# ========================================================================
def adjust_file_length(file_path, max_length):
    """
    تعديل النص داخل ملف ليكون أقل من الحد الأقصى للأحرف.
    """
    try:
        # قراءة النصوص من الملف
        with open(file_path, "r", encoding="utf-8") as f:
            content = f.read().strip()

        # عرض عدد الأحرف الحالي
        current_length = len(content)
        logging.info(f"📄 الملف: {file_path}")
        logging.info(f"🔢 عدد الأحرف الحالي: {current_length}")
        logging.info(f"🔧 الحد الأقصى المسموح به: {max_length}")

        # التحقق من تجاوز الحد الأقصى
        if current_length > max_length:
            logging.info(f"⚠️ النص يتجاوز الحد المسموح به، جاري التعديل...")
            # إزالة الكلمات الزائدة لتقليل النص
            while len(content) > max_length:
                words = content.split()
                words.pop()  # إزالة الكلمة الأخيرة
                content = " ".join(words)  # إعادة بناء النص

            # إعادة كتابة النص المعدل في الملف
            with open(file_path, "w", encoding="utf-8") as f:
                f.write(content)
            logging.info(f"✅ تم تعديل الملف ليكون أقل من {max_length} حرف.")
        else:
            logging.info("✅ النص داخل الحد المسموح به، لا حاجة للتعديل.")
    except Exception as e:
        logging.error(f"❌ خطأ أثناء تعديل الملف: {file_path}, الخطأ: {e}")

def process_file_adjustments():
    """
    تعديل النصوص في ملفات العنوان والوصف والكلمات الدلالية لضمان أنها لا تتجاوز الحدود المسموح بها.
    """
    files_and_limits = {
        "video_title.txt": 98,
        "video_description.txt": 4500,
        "seo_keywords.txt": 400,
    }

    for file_name, max_length in files_and_limits.items():
        file_path = os.path.join(OUTPUT_PATH, file_name)
        adjust_file_length(file_path, max_length)

# ========================================================================
# 🛠️ وظيفة جديدة: حساب نسبة التشابه بين النصوص
# ========================================================================
def calculate_similarity(text1, text2):
    """
    حساب نسبة التشابه بين نصين باستخدام difflib.
    """
    similarity = difflib.SequenceMatcher(None, text1, text2).ratio()
    return similarity * 100  # تحويل النسبة إلى مئوية

# ========================================================================
# 🛠️ وظيفة جديدة: التحقق من التشابه مع الأسماء السابقة
# ========================================================================
def is_similar_to_processed_topics(topic_name, similarity_threshold=50):
    """
    التحقق مما إذا كان الاسم يشبه أيًا من الأسماء المعالجة مسبقًا بنسبة معينة.
    """
    processed_topics_file = os.path.join(OUTPUT_PATH, "processed_topics.txt")
    if not os.path.exists(processed_topics_file):
        return False

    with open(processed_topics_file, "r", encoding="utf-8") as f:
        processed_topics = f.read().splitlines()

    for processed_topic in processed_topics:
        similarity = calculate_similarity(topic_name, processed_topic)
        if similarity >= similarity_threshold:
            logging.info(f"⚠️ الاسم '{topic_name}' يشبه '{processed_topic}' بنسبة {similarity:.2f}%.")
            return True

    return False

# ========================================================================
# 🛠️ وظيفة جديدة: حفظ الاسم الرئيسي المستخرج
# ========================================================================
def save_processed_topic(topic_name):
    """
    حفظ الاسم الرئيسي الذي تم معالجته في ملف لتجنب التكرار.
    """
    processed_topics_file = os.path.join(OUTPUT_PATH, "processed_topics.txt")
    with open(processed_topics_file, "a", encoding="utf-8") as f:
        f.write(f"{topic_name}\n")
    logging.info(f"✅ تم حفظ الاسم الرئيسي '{topic_name}' في ملف الموضوعات المعالجة.")

# ========================================================================
# 🛠️ وظيفة جديدة: استخراج الاسم الرئيسي من النص المُنظف
# ========================================================================
def extract_topic_name_from_cleaned_text(api_key, cleaned_text):
    """
    استخراج الاسم الرئيسي الذي تدور حوله أحداث الموضوع باستخدام الذكاء الصناعي.
    """
    prompt = f"Extract the main name or topic that the following text revolves around. Output only the name or topic without any additional text or labels:\n\n{cleaned_text}"
    return generate_text(api_key, prompt, max_words=10, style='مباشر', text_type='استخراج اسم')

# ========================================================================
# 🛠️ وظيفة جديدة: الحصول على قائمة الموضوعات المستبعدة
# ========================================================================
def get_excluded_topics():
    """
    الحصول على قائمة الموضوعات المستبعدة من ملف processed_topics.txt.
    """
    processed_topics_file = os.path.join(OUTPUT_PATH, "processed_topics.txt")
    if not os.path.exists(processed_topics_file):
        return []

    with open(processed_topics_file, "r", encoding="utf-8") as f:
        excluded_topics = f.read().splitlines()

    return excluded_topics

# ========================================================================
# 🛠️ وظيفة جديدة: التحقق من الموضوعات المستبعدة قبل التوليد
# ========================================================================
def is_topic_excluded_before_generation(topic, excluded_topics, similarity_threshold=70):
    """
    التحقق مما إذا كان الموضوع يشبه أيًا من الموضوعات المستبعدة قبل توليد النص.
    """
    for excluded_topic in excluded_topics:
        similarity = calculate_similarity(topic, excluded_topic)
        if similarity >= similarity_threshold:
            logging.info(f"⚠️ الموضوع '{topic}' يشبه '{excluded_topic}' بنسبة {similarity:.2f}%.")
            return True
    return False

# ========================================================================
# 🏁 نقطة البداية
# ========================================================================
def process_generation():
    """
    التشغيل الرئيسي لتوليد النصوص وحفظها
    """
    logging.info("📄 1 TOPICE GENERATE TEXT - STARTING")
    try:
        # تحميل الإعدادات والمفاتيح
        settings = load_settings()
        api_keys = load_api_keys()
        api_key = random.choice(api_keys["GOOGLE_API_KEYS"])

        # إعدادات المستخدم
        topic = settings.get("TOPIC", "موضوع افتراضي")
        instructions = settings.get("INSTRUCTIONS", "")
        word_count = settings.get("WORD_COUNT", 500)
        style = settings.get("STYLE", "رسمى")
        text_type = settings.get("TEXT_TYPE", "مقال")

        # الحصول على قائمة الموضوعات المستبعدة
        excluded_topics = get_excluded_topics()

        # تكرار العملية حتى يتم توليد موضوع جديد غير مكرر
        while True:
            # إنشاء النصوص مع استبعاد الموضوعات المكررة
            excluded_prompt = f"Do not include the following topics in the generated text: {', '.join(excluded_topics)}." if excluded_topics else ""
            prompt = f"{instructions}\n\n{excluded_prompt}" if instructions else f"{topic}\n\n{excluded_prompt}"

            # توليد النص مع استبعاد الكلمات الرئيسية السابقة
            generated_text = generate_text(api_key, prompt, max_words=word_count, style=style, text_type=text_type,
                                           excluded_keywords=excluded_topics)
            save_text_to_file(generated_text, "original_text.txt")

            # تنظيف النص
            cleaned_text = clean_and_format_text(generated_text)
            save_text_to_file(cleaned_text, "cleaned_text.txt")

            # استخراج الاسم الرئيسي من النص المُنظف
            topic_name = extract_topic_name_from_cleaned_text(api_key, cleaned_text)
            logging.info(f"✅ الاسم الرئيسي المستخرج: {topic_name}")

            # التحقق من عدم تكرار الاسم أو وجود تشابه بنسبة 50% أو أكثر
            if not is_similar_to_processed_topics(topic_name, similarity_threshold=50):
                break  # الخروج من الحلقة إذا كان الموضوع جديدًا

            logging.info(f"⚠️ الاسم '{topic_name}' تم معالجته مسبقًا أو يشبه موضوعًا سابقًا، جاري المحاولة مرة أخرى...")

        # توليد العنوان باستخدام الاسم الرئيسي
        video_title = generate_video_title(api_key, topic, topic_name)
        save_text_to_file(video_title, "video_title.txt")

        # توليد الوصف والكلمات الدلالية
        video_description = generate_video_description(api_key, topic_name, cleaned_text)
        save_text_to_file(video_description, "video_description.txt")

        seo_keywords = generate_seo_keywords(api_key, topic_name)
        save_text_to_file(seo_keywords, "seo_keywords.txt")

        # تعديل النصوص داخل الملفات
        process_file_adjustments()

        # حفظ الاسم الرئيسي الذي تم معالجته
        save_processed_topic(topic_name)

        logging.info("🎉 تم تنفيذ البرنامج بنجاح!")
    except Exception as e:
        logging.error(f"❌ خطأ أثناء التنفيذ: {e}")

if __name__ == "__main__":
    process_generation() اضف شرط كتابة الجمل الموجودة فى مجلد الكلمات الرئيسية ليتجنبها النموزج فى توليد الموضوع التالى