# =====================================
# 📄 1 TOPIC_GENERATE_TEXT.py
# =====================================

import sys
sys.stdout.reconfigure(encoding='utf-8')
sys.stdout.reconfigure(encoding='utf-8')
import os
import logging
import random
import re
import hashlib
import sqlite3
from num2words import num2words
import google.generativeai as genai
from sentence_transformers import SentenceTransformer, util
from fuzzywuzzy import fuzz
from camel_tools.tokenizers.word import simple_word_tokenize
from camel_tools.ner import NERecognizer

# =========================
# 🔧 إعداد المسارات المركزية
# =========================
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")

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

from config import load_api_keys, load_settings

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

# ملفات حفظ النصوص المولدة
GENERATED_TITLES_FILE = os.path.join(OUTPUT_PATH, "generated_titles.txt")
GENERATED_HASHES_FILE = os.path.join(OUTPUT_PATH, "generated_hashes.txt")

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

# =========================
# 🔧 الكلمات الشائعة (Stopwords) - تم إزالة قائمة الكلمات العامة
# =========================
STOPWORDS = set()

# =========================
# 🔧 إعداد قاعدة البيانات
# =========================
DB_PATH = os.path.join(OUTPUT_PATH, "generated_content.db")
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()

# إنشاء جدول العناوين والكيانات الاسمية إذا لم يكن موجودًا
cursor.execute("""
CREATE TABLE IF NOT EXISTS titles (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT UNIQUE,
    hash TEXT UNIQUE,
    generated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")

cursor.execute("""
CREATE TABLE IF NOT EXISTS entities (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title_id INTEGER,
    entity TEXT,
    FOREIGN KEY (title_id) REFERENCES titles(id)
)
""")
conn.commit()

# =========================
# 🔧 إعداد نموذج CAMeL Tools لـ NER
# =========================
try:
    logging.info("تحميل نموذج CAMeL Tools لـ NER")
    ner = NERecognizer.pretrained()
except Exception as e:
    logging.error(f"❌ فشل في تحميل نموذج CAMeL Tools لـ NER: {e}")
    sys.exit(1)

# =========================
# 🔧 الوظائف المساعدة
# =========================

def load_generated_topics_db():
    """تحميل العناوين المولدة سابقاً من قاعدة البيانات"""
    cursor.execute("SELECT title FROM titles")
    return [row[0] for row in cursor.fetchall()]

def append_title_db(title, title_hash, entities):
    """إضافة عنوان جديد وهاش له وكياناته الاسمية إلى قاعدة البيانات"""
    try:
        cursor.execute("INSERT INTO titles (title, hash) VALUES (?, ?)", (title, title_hash))
        title_id = cursor.lastrowid
        for entity in entities:
            cursor.execute("INSERT INTO entities (title_id, entity) VALUES (?, ?)", (title_id, entity))
        conn.commit()
        logging.info("✅ تم حفظ العنوان والكيانات الاسمية في قاعدة البيانات")
    except sqlite3.IntegrityError:
        logging.warning("⚠️ العنوان موجود مسبقاً في قاعدة البيانات")

def hash_text(text):
    """توليد هاش للنص المعطى"""
    return hashlib.md5(text.encode()).hexdigest()

def read_generated_hashes(file_path):
    """قراءة الهاشات المولدة سابقاً من الملف"""
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            return {line.strip() for line in f if line.strip()}
    except FileNotFoundError:
        return set()

def append_hash(file_path, text):
    """إضافة هاش جديد إلى ملف الهاشات"""
    with open(file_path, 'a', encoding='utf-8') as f:
        f.write(f"{hash_text(text)}\n")

def save_text_to_file(text, filename):
    """حفظ النص المولد إلى ملف"""
    with open(os.path.join(OUTPUT_PATH, filename), 'w', encoding='utf-8') as f:
        f.write(text)
    logging.info(f"✅ تم حفظ الملف: {filename}")

def generate_text(api_key, prompt, max_words=500, style="رسمي", text_type="مقال"):
    """توليد النصوص باستخدام Google Generative AI"""
    try:
        genai.configure(api_key=api_key)
        model_genai = genai.GenerativeModel('gemini-pro')

        modified_prompt = f"قم بتوليد {text_type} {style} باللغة العربية بحوالي {max_words} كلمة حول الموضوع التالي:\n\n{prompt}"

        logging.info(f"🔄 إرسال البرومبت: {modified_prompt}")
        response = model_genai.generate_content(modified_prompt)
        if response.text:
            logging.info(f"✅ تم توليد {text_type} بنجاح")
            return response.text.strip()
        else:
            logging.error(f"❌ لم يتم توليد نص من النموذج لـ {text_type}")
            return ""
    except Exception as e:
        logging.error(f"❌ خطأ أثناء توليد {text_type}: {e}")
        return ""

def extract_main_phrases_simple(text):
    """استخراج العبارات الرئيسية باستخدام طريقة بسيطة"""
    words = text.split()
    phrases = set()
    for i in range(len(words) - 1):
        phrase2 = ' '.join(words[i:i + 2])
        if all(word not in STOPWORDS for word in phrase2.split()):
            phrases.add(phrase2)
        if i < len(words) - 2:
            phrase3 = ' '.join(words[i:i + 3])
            if all(word not in STOPWORDS for word in phrase3.split()):
                phrases.add(phrase3)
    return phrases

def extract_keywords(titles):
    """استخراج الكلمات المفتاحية من قائمة العناوين"""
    main_phrases = set()
    for title in titles:
        phrases = extract_main_phrases_simple(title)
        main_phrases.update(phrases)
    return main_phrases

def extract_entities(text):
    """استخراج الكيانات الاسمية من النص باستخدام CAMeL Tools"""
    tokens = simple_word_tokenize(text)
    tags = ner.predict_sentence(tokens)  # قائمة من العلامات
    named_entities = set()
    current_entity = []
    for token, tag in zip(tokens, tags):
        if tag.startswith('B-'):
            if current_entity:
                named_entities.add(' '.join(current_entity))
                current_entity = []
            current_entity.append(token)
        elif tag.startswith('I-') and current_entity:
            current_entity.append(token)
        else:
            if current_entity:
                named_entities.add(' '.join(current_entity))
                current_entity = []
    if current_entity:
        named_entities.add(' '.join(current_entity))
    return named_entities

def is_duplicate(new_topic, existing_topics, existing_hashes, similarity_threshold=0.8, fuzzy_threshold=90):
    """التحقق من تكرار الموضوع بناءً على الهاش والتشابه."""
    if not new_topic:
        return True

    new_hash = hash_text(new_topic)
    if new_hash in existing_hashes:
        return True

    # استخراج الكلمات الرئيسية من الموضوع الجديد
    new_words = extract_main_words(new_topic)

    for topic in existing_topics:
        existing_words = set(extract_main_words(topic))
        if not new_words or not existing_words:
            continue
        intersection = new_words.intersection(existing_words)
        similarity_ratio = len(intersection) / len(new_words)
        if similarity_ratio >= similarity_threshold:
            logging.warning(f"⚠️ الموضوع مشابه بنسبة {similarity_ratio*100}% لعنوان موجود: {topic}")
            return True

    if existing_topics:
        new_embedding = model.encode(new_topic, convert_to_tensor=True)
        existing_embeddings = model.encode(existing_topics, convert_to_tensor=True)
        similarities = util.pytorch_cos_sim(new_embedding, existing_embeddings)
        max_similarity = similarities.max().item()
        if max_similarity >= similarity_threshold:
            return True

    for topic in existing_topics:
        similarity = fuzz.ratio(new_topic, topic)
        if similarity >= fuzzy_threshold:
            return True

    return False

def extract_main_words(text):
    """استخراج الكلمات الرئيسية من النص."""
    text = re.sub(r'[^\w\s]', '', text)
    words = text.split()
    main_words = [word for word in words if word not in STOPWORDS]
    return set(main_words)

def generate_new_topic(api_key, base_topic, excluded_words):
    """توليد موضوع جديد مع تجنب استخدام الكلمات المستبعدة."""
    prompt = f"اقترح موضوعًا جديدًا مرتبطًا بـ: {base_topic}."
    if excluded_words:
        excluded_phrases = '، '.join(excluded_words)
        prompt += f" تجنب استخدام الكلمات التالية: {excluded_phrases}"
    return generate_text(api_key, prompt, max_words=30, style='إبداعي', text_type='موضوع')

def generate_new_topic_unique(api_key, base_topic, existing_topics, existing_hashes, excluded_words):
    """توليد موضوع جديد فريد مع تجنب استخدام الكلمات المستبعدة."""
    max_attempts = 5
    for attempt in range(max_attempts):
        new_topic = generate_new_topic(api_key, base_topic, excluded_words)
        if new_topic and not is_duplicate(new_topic, existing_topics, existing_hashes):
            logging.info(f"🎯 الموضوع الجديد الفريد: {new_topic}")
            return new_topic
        logging.warning(f"⚠️ محاولة توليد موضوع جديد (المحاولة {attempt + 1})...")
    raise RuntimeError("⚠️ فشل توليد موضوع فريد بعد عدة محاولات.")

def clean_and_format_text(text):
    """تنظيف وتنسيق النص."""
    if not text:
        return ""
    logging.info("🔄 بدء تنظيف النص...")
    text = re.sub(r'\s+', ' ', text).strip()
    text = re.sub(r'[^\w\s.,!?]', '', text)
    text = re.sub(r'\d+', lambda x: num2words(int(x.group()), lang='ar'), text)
    logging.info("✅ تم تنظيف النص بنجاح.")
    return text

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

        if len(content) > max_length:
            logging.info(f"⚠️ النص يتجاوز الحد المسموح به، جاري التعديل...")
            content = content[:max_length]
            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 generate_video_title(api_key, cleaned_text):
    """توليد عنوان فيديو جذاب بناءً على النص المنظف."""
    prompt = (
        f"اكتب عنوان فيديو جذاب باللغة العربية بناءً على النص التالي ، مضافا الية اسم الحدث او الشخصية او الموضوع لجعل الموضوع اكثر دقة:\n\n"
        f"'{cleaned_text}'.\n\n"
        "الهدف هو جعل العنوان دقيقًا، يثير الفضول، ويعبر عن جوهر الموضوع. "
        "بعد العنوان، أضف 3 هاشتاجات عربية رائجة ومرتبطة بالنص. "
        "تجنب استخدام العبارات الرئيسية المستخدمة في العناوين السابقة. "
        "أخرج فقط العنوان متبوعًا بالهاشتاجات، بدون أي مقدمات أو تعليقات إضافية."
    )
    return generate_text(api_key, prompt, max_words=15, style='دقيق وواضح', text_type='عنوان فيديو')

def generate_video_description(api_key, topic, cleaned_text):
    """توليد وصف الفيديو مع الهاشتاجات."""
    prompt = (
        f"اكتب وصفًا تفصيليًا وجذابًا باللغة العربية للفيديو حول الموضوع '{topic}'. "
        f"استخدم النص التالي كمرجع:\n\n{cleaned_text}\n\n"
        "تأكد من أن الوصف شاملاً ويتضمن 30 هاشتاج رائج ذو صلة بالموضوع لزيادة الوصول والتفاعل."
    )
    return generate_text(api_key, prompt, max_words=200, style='مفصل', text_type='وصف فيديو')

def generate_seo_keywords(api_key, topic):
    """توليد كلمات دلالية SEO."""
    prompt = (
        f"اكتب قائمة بكلمات دلالية (SEO) باللغة العربية للموضوع '{topic}'. "
        "تأكد من أن الكلمات دلالية ومرتبطة ببحث يوتيوب ويجب فصلها بفواصل (`,`). "
        "لا تتجاوز 350 حرفًا في الإجمالي."
    )
    return generate_text(api_key, prompt, max_words=30, style='مباشر', text_type='كلمات دلالية')

# =========================
# 🏁 نقطة البداية
# =========================

def process_generation(model):
    """العملية الرئيسية لتوليد المحتوى."""
    logging.info("📄 1 TOPIC_GENERATE_TEXT - STARTING")
    try:
        # تحميل الإعدادات
        settings = load_settings()
        api_keys = load_api_keys()
        api_key = random.choice(api_keys["GOOGLE_API_KEYS"])

        # الإعدادات الأساسية
        base_topic = settings.get("TOPIC", "")
        word_count = settings.get("WORD_COUNT", 500)
        style = settings.get("STYLE", "رسمي")
        text_type = settings.get("TEXT_TYPE", "مقال")

        # تحميل المحتوى السابق
        generated_titles = load_generated_topics_db()
        logging.info(f"🔑 عدد العناوين المولدة سابقًا: {len(generated_titles)}")

        # استخراج الكلمات الرئيسية من العناوين السابقة
        existing_words = set()
        for title in generated_titles:
            existing_words.update(extract_main_words(title))
        logging.info(f"🔑 الكلمات الرئيسية المستخدمة سابقًا: {existing_words}")

        # قراءة الهاشات المولدة سابقاً من الملف
        generated_hashes = read_generated_hashes(GENERATED_HASHES_FILE)
        logging.info(f"🔑 عدد الهاشات المستخدمة سابقًا: {len(generated_hashes)}")

        # توليد محتوى جديد فريد
        new_topic = generate_new_topic_unique(api_key, base_topic, generated_titles, generated_hashes, existing_words)

        # توليد النص الأساسي
        main_text = generate_text(api_key, new_topic, word_count, style, text_type)
        cleaned_text = clean_and_format_text(main_text)

        # حفظ النصوص
        save_text_to_file(main_text, "original_text.txt")
        save_text_to_file(cleaned_text, "cleaned_text.txt")

        # توليد وحفظ العنوان
        video_title = generate_video_title(api_key, cleaned_text)
        save_text_to_file(video_title, "video_title.txt")

        # استخراج الكيانات الاسمية من العنوان الجديد
        title_entities = extract_entities(video_title)
        logging.info(f"🔑 الكيانات الاسمية في العنوان الجديد: {title_entities}")

        # تحديث قاعدة البيانات والهاشات
        title_hash = hash_text(video_title)
        append_title_db(video_title, title_hash, title_entities)
        append_hash(GENERATED_HASHES_FILE, video_title)

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

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

        # تعديل أطوال الملفات لضمان الامتثال للحدود المسموح بها
        process_file_adjustments()

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

if __name__ == "__main__":
    # تحميل نموذج SentenceTransformer مرة واحدة هنا
    logging.info("Use pytorch device_name: cpu")
    logging.info("Load pretrained SentenceTransformer: distiluse-base-multilingual-cased")
    model = SentenceTransformer('distiluse-base-multilingual-cased')
    process_generation(model)
 اشرح هذا الكود