import sys
sys.stdout.reconfigure(encoding='utf-8')
import os
import re
import time
import logging
import psutil
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException, ElementClickInterceptedException
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from dotenv import load_dotenv

# تحميل المتغيرات البيئية من ملف .env
load_dotenv(dotenv_path=os.path.join('D:/YouTubeGen Pro 3', 'config', '.env'))

# قراءة المتغيرات البيئية
CHROMEDRIVER_PATH = os.getenv('CHROMEDRIVER_PATH')
CANARY_BINARY_PATH = os.getenv('CANARY_BINARY_PATH')
USER_DATA_DIR = os.getenv('USER_DATA_DIR')
VIDEO_PATH = os.getenv('VIDEO_PATH')
TITLE_PATH = os.getenv('TITLE_PATH')
DESCRIPTION_PATH = os.getenv('DESCRIPTION_PATH')
KEYWORDS_PATH = os.getenv('KEYWORDS_PATH')

# قائمة البروفايلات
PROFILES = ["Default", "Profile 2"]  # أسماء البروفايلات

# إعداد تسجيل الرسائل
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.StreamHandler(sys.stdout),
        logging.FileHandler("app.log", encoding="utf-8")
    ]
)

def kill_chrome_canary_taskkill():
    """إغلاق أي عملية تعمل في الخلفية خاصة بمتصفح Chrome Canary."""
    try:
        canary_executable = os.path.abspath(CANARY_BINARY_PATH)
        logging.info("🔎 محاولة إغلاق أي عملية لـ Chrome Canary بواسطة psutil...")
        found_any = False
        for proc in psutil.process_iter(['pid', 'name', 'exe']):
            try:
                exe_path = proc.info['exe']
                if exe_path and exe_path.lower() == canary_executable.lower():
                    proc.kill()
                    found_any = True
                    logging.info(f"✅ تم إغلاق عملية Chrome Canary: PID {proc.pid}")
            except (psutil.NoSuchProcess, psutil.AccessDenied):
                pass
        if not found_any:
            logging.info("ℹ️ لا توجد أية عملية لـ Chrome Canary قيد التشغيل حاليًا.")
    except Exception as e:
        logging.warning(f"⚠️ حدث خطأ أثناء محاولة قتل Chrome Canary بالمسار: {e}")

def remove_profile_lock_files(user_data_dir, profile_name):
    """حذف ملفات القفل إن وجدت في مجلد الـ Profile."""
    profile_dir = os.path.join(user_data_dir, profile_name)
    lock_files = ["LOCK", "SingletonLock", "SingletonCookie", "SingletonSocket"]
    if not os.path.exists(profile_dir):
        logging.warning(f"⚠️ مجلد البروفايل غير موجود: {profile_dir}")
        return
    for lf in lock_files:
        lock_path = os.path.join(profile_dir, lf)
        if os.path.exists(lock_path):
            try:
                os.remove(lock_path)
                logging.info(f"✅ تم حذف ملف القفل: {lock_path}")
            except Exception as e:
                logging.warning(f"⚠️ تعذر حذف ملف القفل {lock_path}: {e}")

def remove_non_bmp_chars(text):
    """إزالة الأحرف غير المدعومة من النص."""
    return re.sub(r'[^\u0000-\uFFFF]', '', text)

def clear_and_type(element, text):
    """تفريغ الحقل ثم إدخال النص."""
    try:
        element.click()
        element.clear()
    except Exception as e:
        logging.warning(f"⚠️ فشل في مسح الحقل باستخدام الطرق التقليدية: {e}")
        bot.execute_script("arguments[0].value = '';", element)
    text = remove_non_bmp_chars(text)
    element.send_keys(text)
    logging.info(f"✅ تم إدخال النص: {text}")

def read_file_content(file_path):
    """قراءة محتوى الملف وإرجاعه بعد التأكد من أنه غير فارغ."""
    try:
        with open(file_path, "r", encoding="utf-8") as file:
            content = file.read().strip()
            if content:
                logging.info(f"📄 تم قراءة الملف بنجاح: {file_path}")
                return content
            else:
                logging.error(f"⚠️ الملف فارغ: {file_path}")
                return None
    except Exception as e:
        logging.error(f"⚠️ حدث خطأ أثناء قراءة الملف {file_path}: {e}")
        return None

def find_element_by_js_or_xpath(bot, js_selector, xpath_selector, timeout=30):
    """العثور على عنصر باستخدام JavaScript أو XPath."""
    try:
        if js_selector:
            element = bot.execute_script(f"return {js_selector}")
            if element:
                logging.info(f"✅ تم العثور على العنصر باستخدام JavaScript: {js_selector}")
                return element
    except Exception as e:
        logging.warning(f"❌ فشل العثور على العنصر باستخدام JavaScript: {e}")
    try:
        element = WebDriverWait(bot, timeout).until(EC.presence_of_element_located((By.XPATH, xpath_selector)))
        logging.info(f"✅ تم العثور على العنصر باستخدام XPath: {xpath_selector}")
        return element
    except TimeoutException:
        logging.error(f"⚠️ لم يتم العثور على العنصر باستخدام XPath: {xpath_selector}")
        return None

def type_file_path(file_input_element, file_path):
    """إدخال مسار الملف باستخدام send_keys."""
    logging.info(f"📁 إدخال مسار الملف: {file_path}")
    try:
        file_input_element.send_keys(file_path)
        logging.info("✅ تم إدخال مسار الملف بنجاح.")
    except Exception as e:
        logging.error(f"⚠️ فشل في إدخال مسار الملف: {e}")

def scroll_down(bot, pixels=500):
    """التمرير لأسفل في الصفحة."""
    bot.execute_script(f"window.scrollBy(0, {pixels});")
    logging.info(f"🔻 تم التمرير لأسفل بمقدار {pixels} بيكسل.")

def handle_tags_input(bot):
    """البحث عن حقل إدخال الكلمات الدلالية."""
    scroll_down(bot)
    tags_input = find_element_by_js_or_xpath(bot, None, '//input[@id="text-input" and @aria-label="العلامات"]')
    if tags_input:
        return tags_input
    try:
        more_options_button = bot.find_element(By.XPATH, '//*[@id="toggle-button"]/ytcp-button-shape/button')
        bot.execute_script("arguments[0].click();", more_options_button)
        logging.info("📑 تم الضغط على زر 'عرض المزيد من الخيارات'.")
        return find_element_by_js_or_xpath(bot, None, '//input[@id="text-input" and @aria-label="العلامات"]')
    except NoSuchElementException:
        logging.error("⚠️ لم يتم العثور على زر 'عرض المزيد من الخيارات'.")
        return None

def verify_input_success(element, expected_text):
    """التحقق من نجاح إدخال النص في الحقل."""
    entered_text = element.get_attribute("value")
    if expected_text.strip() == entered_text.strip():
        logging.info("✅ تم التحقق من إدخال النص بنجاح.")
        return True
    else:
        logging.warning("❌ فشل التحقق من إدخال النص.")
        return False

def upload_video(bot):
    """عملية رفع الفيديو إلى يوتيوب مع خطوات واضحة."""
    try:
        bot.get("https://studio.youtube.com")
        logging.info("🌐 فتح استوديو يوتيوب...")

        upload_button = WebDriverWait(bot, 30).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="upload-icon"]')))
        upload_button.click()
        logging.info("📤 تم الضغط على زر الرفع.")

        file_input = WebDriverWait(bot, 30).until(EC.presence_of_element_located((By.XPATH, '//input[@type="file"]')))
        logging.info("📂 تم العثور على حقل رفع الملفات.")
        type_file_path(file_input, VIDEO_PATH)

        title_input = WebDriverWait(bot, 30).until(
            EC.presence_of_element_located((By.XPATH,
                '//div[@id="textbox" and @aria-label="إضافة عنوان يصف الفيديو (يُرجى كتابة الرمز @ للإشارة إلى قناة معيّنة.)"]'))
        )
        if title_input:
            title = read_file_content(TITLE_PATH)
            if title:
                clear_and_type(title_input, title)

        desc_input = WebDriverWait(bot, 30).until(
            EC.presence_of_element_located((By.XPATH,
                '//div[@id="textbox" and @aria-label="إخبار المشاهدين عن الفيديو (يُرجى كتابة الرمز @ للإشارة إلى قناة معيّنة.)"]'))
        )
        if desc_input:
            description = read_file_content(DESCRIPTION_PATH)
            if description:
                clear_and_type(desc_input, description)

        tags_input = handle_tags_input(bot)
        if tags_input:
            keywords = read_file_content(KEYWORDS_PATH)
            if keywords:
                words_to_remove = ["الكلمة1", "الكلمة2"]
                cleaned_keywords = clean_keywords(keywords, words_to_remove)
                formatted_keywords = format_keywords(cleaned_keywords)
                for keyword in formatted_keywords:
                    tags_input.send_keys(keyword)
                    tags_input.send_keys(Keys.ENTER)
                    logging.info(f"✅ تم إدخال الكلمة الدلالية: {keyword}")
                    time.sleep(0.5)
            else:
                logging.error("⚠️ لم يتم العثور على الكلمات الدلالية.")
        else:
            logging.error("⚠️ فشل في العثور على حقل العلامات.")

        for i in range(3):
            next_button = WebDriverWait(bot, 30).until(EC.element_to_be_clickable((By.XPATH, '//ytcp-button[@id="next-button"]')))
            next_button.click()
            logging.info(f"➡️ تم الضغط على زر 'التالي' ({i+1}/3).")
            time.sleep(2)

        done_button = WebDriverWait(bot, 30).until(EC.element_to_be_clickable((By.XPATH, '//ytcp-button[@id="done-button"]')))
        done_button.click()
        logging.info("✅ تم إنهاء عملية الرفع بنجاح.")
        time.sleep(5)
        return True

    except Exception as e:
        logging.error(f"⚠️ خطأ أثناء رفع الفيديو: {e}")
        return False

def clean_keywords(text, words_to_remove):
    """إزالة الكلمات غير المرغوب فيها من النص."""
    for word in words_to_remove:
        text = text.replace(word, "")
    return text

def format_keywords(keywords):
    """تنسيق الكلمات الدلالية."""
    keywords = re.sub(r'[*\-|():.]', '', keywords)
    sentences = re.split(r'[.!?،]', keywords)
    formatted_sentences = [sentence.strip() for sentence in sentences if sentence.strip()]
    return formatted_sentences

def wait_and_find_element(bot, by, value, timeout=30, message=""):
    """Helper function to wait for and find elements with better error handling"""
    try:
        element = WebDriverWait(bot, timeout).until(
            EC.presence_of_element_located((by, value))
        )
        if message:
            logging.info(message)
        return element
    except TimeoutException:
        logging.error(f"⚠️ Timeout waiting for element: {value}")
        return None

def click_with_retry(element, max_attempts=3):
    """Helper function to retry clicking with multiple attempts"""
    for attempt in range(max_attempts):
        try:
            element.click()
            return True
        except ElementClickInterceptedException:
            if attempt == max_attempts - 1:
                raise
            time.sleep(1)
    return False

def post_to_facebook(bot, video_url):
    """Post video link to Facebook page using exact selectors"""
    try:
        # Navigate to the Facebook page
        bot.get("https://www.facebook.com/oddityworldtubee/")
        logging.info("🌐 Opening Facebook page...")

        # Wait for page load and scroll slightly
        time.sleep(5)
        bot.execute_script("window.scrollBy(0, 100);")

        # Find "Create Post" area using the specific class
        create_post_button = wait_and_find_element(
            bot,
            By.CSS_SELECTOR,
            'div[class*="x1i10hfl"][class*="x1n2onr6"][class*="xt7dq6l"][role="button"]',
            timeout=10,
            message="Found create post button"
        )

        if create_post_button:
            click_with_retry(create_post_button)
            time.sleep(3)

        # Find post box using exact class and attributes
        post_box = wait_and_find_element(
            bot,
            By.CSS_SELECTOR,
            'div.xzsf02u.x1a2a7pz.x1n2onr6.x14wi4xw.x9f619.x1lliihq.x5yr21d.xh8yej3[contenteditable="true"][role="textbox"]',
            timeout=10,
            message="Found post box"
        )

        if not post_box:
            # Try alternative selector
            post_box = wait_and_find_element(
                bot,
                By.CSS_SELECTOR,
                'div[aria-label="بم تفكر؟"][role="textbox"]',
                timeout=10
            )

        if not post_box:
            raise Exception("Could not find post box")

        # Click and enter text
        click_with_retry(post_box)
        time.sleep(1)

        # Read the video title from the file
        video_title_path = os.path.join("D:/YouTubeGen Pro 3", "OUTPUT", "Pro Output Text", "video_title.txt")
        video_title = read_file_content(video_title_path)
        if not video_title:
            video_title = "New video uploaded"  # Fallback in case the file is empty or not found

        # Enter text without emoji to avoid encoding issues
        post_text = f"{video_title}: {video_url}"
        for char in post_text:
            post_box.send_keys(char)
            time.sleep(0.1)

        logging.info("📝 Entered post text.")
        time.sleep(2)

        # Find publish button using exact class
        publish_button = wait_and_find_element(
            bot,
            By.CSS_SELECTOR,
            'div.x1i10hfl.xjbqb8w.x1ejq31n.xd10rxx.x1sy0etr.x17r0tee.x972fbf.xcfux6l.x1qhh985.xm0m39n.xe8uvvx.xdj266r.x11i5rnm.xat24cr.x1mh8g0r.xexx8yu.x4uap5.x18d9i69.xkhd6sd.x16tdsg8.x1hl2dhg.xggy1nq.x1h6gzvc.x1o1ewxj.x3x9cwd.x1e5q0jg.x13rtm0m.x87ps6o.x1lku1pv.x1a2a7pz.x9f619.x3nfvp2.xdt5ytf.xl56j7k.x1n2onr6.xh8yej3[role="button"][aria-label="نشر"]',
            timeout=10
        )

        if not publish_button:
            # Try alternative selector
            publish_button = wait_and_find_element(
                bot,
                By.CSS_SELECTOR,
                'div[aria-label="نشر"][role="button"]',
                timeout=10
            )

        if not publish_button:
            raise Exception("Could not find publish button")

        # Click publish and wait
        click_with_retry(publish_button)
        logging.info("✅ Clicked publish button")
        time.sleep(10)

        return True

    except Exception as e:
        logging.error(f"⚠️ Failed to post to Facebook: {str(e)}")
        return False

def setup_browser(profile):
    """Initialize Chrome browser with improved options"""
    options = Options()
    options.binary_location = CANARY_BINARY_PATH
    options.add_argument(f"--user-data-dir={USER_DATA_DIR}")
    options.add_argument(f"--profile-directory={profile}")
    options.add_argument("--start-maximized")
    options.add_argument("--disable-notifications")
    options.add_argument("--disable-gpu")
    options.add_argument("--no-sandbox")
    options.add_argument("--disable-dev-shm-usage")
    options.add_argument('--lang=en-US')
    options.add_argument('--disable-extensions')
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option("useAutomationExtension", False)
    options.add_argument('--force-device-scale-factor=1')

    service = Service(executable_path=CHROMEDRIVER_PATH)
    return webdriver.Chrome(service=service, options=options)

def get_video_url(bot):
    """الحصول على رابط الفيديو بعد الرفع."""
    try:
        video_url_element = WebDriverWait(bot, 30).until(
            EC.presence_of_element_located((By.XPATH, '//a[@class="style-scope ytcp-video-info"]'))
        )
        video_url = video_url_element.get_attribute("href")
        logging.info(f"🔗 تم الحصول على رابط الفيديو: {video_url}")
        return video_url
    except Exception as e:
        logging.error(f"⚠️ فشل في الحصول على رابط الفيديو: {e}")
        return None

def main():
    max_retries = 3
    retry_delay = 60
    wait_before_close = 420

    for profile in PROFILES:
        attempts = 0
        logging.info(f"🚀 بدء عملية الرفع باستخدام البروفايل {profile}...")

        while attempts < max_retries:
            kill_chrome_canary_taskkill()
            time.sleep(2)
            remove_profile_lock_files(USER_DATA_DIR, profile)

            bot = setup_browser(profile)

            try:
                success = upload_video(bot)
                if success:
                    video_url = get_video_url(bot)
                    if video_url:
                        logging.info(f"🎉 تم رفع الفيديو بنجاح على البروفايل {profile}.")
                        logging.info(f"⏳ الانتظار لمدة {wait_before_close // 60} دقيقة قبل إغلاق المتصفح...")
                        time.sleep(wait_before_close)

                        # إذا كان البروفايل الحالي هو الافتراضي (Default)، قم بنشر الرابط على فيس بوك
                        if profile == "Default":
                            logging.info("🔄 الانتقال إلى البروفايل الافتراضي لنشر الرابط على Facebook...")
                            bot.quit()

                            # استخدام البروفايل الافتراضي
                            bot = setup_browser("Default")
                            post_to_facebook(bot, video_url)

                    break
                else:
                    attempts += 1
                    logging.error(f"❌ فشل رفع الفيديو على البروفايل {profile}. المحاولة {attempts} من {max_retries}.")
                    if attempts < max_retries:
                        logging.info(f"⏳ انتظار لمدة {retry_delay} ثانية قبل إعادة المحاولة...")
                        time.sleep(retry_delay)
            finally:
                bot.quit()

        if attempts == max_retries:
            logging.error(f"❌ فشلت جميع المحاولات على البروفايل {profile}.")

    logging.info("🛑 تم إنهاء البرنامج.")

if __name__ == "__main__":
    main() افهم انا عايز اية بالتحديد انا عايز الكود دة كامل بس عايز بدل ما يقوم باغلاق كل العمليات المفتوحة فى المتصفح يقوم باغلاق البروفيل المحدد فقط ويسيب باقى البروفيلات شغالة افصل اعدادات البروفيل بحيث اعدادات السيطب تكون منفصلى لكل بروفيل بيتفتح ومتاثرش على البروفيل المفتوح التانى دير العملية بزكاء