from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import TimeoutException
from bs4 import BeautifulSoup, NavigableString, Tag
from kameleo.local_api_client import KameleoLocalApiClient
import json
import time
import os
import random
import base64
import mysql.connector

# --- Конфигурация ---
kameleo_port = 5050
EDITOR_URL = "https://dzen.ru/profile/editor/id/686e295c4763b6759f36a8a1/688894e4519fc1178436201b/edit"
PROFILE_NAME = "Dzen_test"

DB_CONFIG = {
    'host': '192.168.8.100',
    'user': 'root',
    'password': 'BXiQLt3G',
    'database': 'led_topics_db',
    'port': 3307,
}

EDITOR_URL = "https://dzen.ru/profile/editor/ledinform/publications"
IMAGE_FOLDER = r"C:\Users\Evgen\Documents\generate_img"  # Папка с изображениями


# === Запуск профиля Kameleo ===
def start_kameleo_profile(profile_name="Dzen_test"):
    client = KameleoLocalApiClient(endpoint=f'http://localhost:{kameleo_port}')
    profiles = client.profile.list_profiles()
    profile_id = None
    for prof in profiles:
        print(f"ID: {prof.id} | Name: {prof.name}")
        if prof.name == profile_name:
            profile_id = prof.id
            break
    if profile_id is None:
        raise Exception(f"Профиль {profile_name} не найден!")

    client.profile.start_profile(profile_id)
    return client, profile_id


# === Подключение Selenium к Kameleo браузеру ===
def init_kameleo_selenium(profile_id):
    options = Options()
    options.add_experimental_option('kameleo:profileId', profile_id)
    driver = webdriver.Remote(
        command_executor=f'http://localhost:{kameleo_port}/webdriver',
        options=options
    )
    return driver


# === Открытие редактора (без загрузки кук!) ===
def open_editor(driver):
    print("🌐 Открываем редактор...")
    driver.get(EDITOR_URL)
    
    # Ждём загрузки страницы
    try:
        WebDriverWait(driver, 15).until(
            EC.presence_of_element_located((By.TAG_NAME, 'body'))
        )
        print("✅ Страница загружена")
    except:
        print("❌ Страница не загружена за 15 секунд")
        return False

    # Пытаемся закрыть всплывающее окно
    try:
        close_btn = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, '//button[@aria-label="Закрыть"]'))
        )
        close_btn.click()
        print("✅ Всплывающее окно закрыто")
    except:
        print("ℹ️ Всплывающее окно не найдено или не открыто")

    # Проверяем, загружен ли редактор
    try:
        WebDriverWait(driver, 15).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "button[data-testid='add-publication-button']"))
        )
        print("✅ Редактор загружен")
        return True
    except Exception as e:
        print(f"❌ Редактор не загружен: {e}")
        return False


# === Получаем случайную статью из базы ===
def get_article_from_db():
    try:
        conn = mysql.connector.connect(**DB_CONFIG)
        cursor = conn.cursor(dictionary=True)
        query = """
        SELECT topic, content 
        FROM led_topics
        WHERE is_archived = 0 
          AND content IS NOT NULL 
          AND content != ''
        ORDER BY RAND()
        LIMIT 1;
        """
        cursor.execute(query)
        result = cursor.fetchone()
        cursor.close()
        conn.close()
        return result
    except Exception as e:
        print(f"❌ Ошибка при подключении к БД: {e}")
        return None


# === Закрытие подсказок в редакторе ===
def close_tips(driver):
    try:
        close_button = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, '//div[@role="button" and @aria-label="Закрыть"]'))
        )
        close_button.click()
        print("✅ Подсказка закрыта")
    except:
        print("ℹ️ Подсказка не найдена или уже закрыта")

# === Извлечение заголовка из первого <p> ===
def extract_title_from_first_p(soup):
    p = soup.find('p')
    if not p:
        return "Без заголовка"
    title = p.get_text(strip=True)
    p.decompose()
    return title
    
# === Создание новой статьи (нажимаем "Написать статью") ===
def create_new_article(driver):
    try:
        add_button = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.CSS_SELECTOR, "button[data-testid='add-publication-button']"))
        )
        add_button.click()
        print("✅ Клик по кнопке 'Написать статью'")

        write_button = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, '//span[text()="Написать статью"]'))
        )
        write_button.click()
        print("✅ Выбрана публикация 'Написать статью'")
    except Exception as e:
        print(f"❌ Ошибка при создании новой статьи: {e}")
        return False
    return True


# === Вставка заголовка статьи через send_keys ===
def insert_title(driver, title):
    try:
        title_field = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "div.public-DraftEditor-content[contenteditable='true']"))
        )
        title_field.click()
        time.sleep(0.5)
        actions = ActionChains(driver)
        actions.send_keys(title)
        actions.perform()
        print("✅ Заголовок успешно вставлен")
    except Exception as e:
        print(f"❌ Ошибка при вставке заголовка: {e}")


# === Вставка форматированного контента ===
def send_formatted_content(driver, html):
    editor = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, "/html/body/div[2]/div[2]/div[1]/div[2]/div[2]/div[2]/div/div[2]/div[1]/div/div/div/div/div/div"))
        )
    editor.click()
    time.sleep(0.5)

    soup = BeautifulSoup(html, 'html.parser')
    
    # Создаём ActionChains один раз и передаём внутрь
    actions = ActionChains(driver)

    def send_text_with_formatting(element, actions):
        if isinstance(element, NavigableString):
            text = element.strip()
            if text:
                actions.send_keys(text)
            return

        # Применяем стили
        if element.name in ['b', 'strong']:
            actions.key_down(Keys.CONTROL).send_keys('b').key_up(Keys.CONTROL)
        if element.name in ['i', 'em']:
            actions.key_down(Keys.CONTROL).send_keys('i').key_up(Keys.CONTROL)
        if element.name == 'u':
            actions.key_down(Keys.CONTROL).key_down(Keys.SHIFT).send_keys('u').key_up(Keys.SHIFT).key_up(Keys.CONTROL)

        if element.name == 'a':
            link_text = element.get_text(strip=True)
            link_url = element.get('href')
            if link_text and link_url:
                actions.send_keys(link_text)
                actions.perform()
                for _ in range(len(link_text)):
                    actions = ActionChains(driver)
                    actions.key_down(Keys.SHIFT).send_keys(Keys.LEFT).key_up(Keys.SHIFT)
                    actions.perform()
                try:
                    link_button = WebDriverWait(driver, 5).until(
                        EC.element_to_be_clickable((By.XPATH, "//div[contains(@class, 'editor-toolbar__linkTools-9h')]"))
                    )
                    link_button.click()
                    link_input = WebDriverWait(driver, 5).until(
                        EC.element_to_be_clickable((By.XPATH, "//input[contains(@placeholder, 'Введите ссылку')]"))
                    )
                    link_input.clear()
                    link_input.send_keys(link_url)
                    link_input.send_keys(Keys.ENTER)
                    print(f"✅ Вставлена ссылка: {link_text} -> {link_url}")
                except Exception as e:
                    print(f"❌ Не удалось вставить ссылку: {e}")
                return

        for child in element.children:
            send_text_with_formatting(child, actions)
            if isinstance(child, NavigableString):
                actions.send_keys(' ')

        if element.name in ['b', 'strong']:
            actions.key_down(Keys.CONTROL).send_keys('b').key_up(Keys.CONTROL)
            actions.send_keys(' ')
        if element.name in ['i', 'em']:
            actions.key_down(Keys.CONTROL).send_keys('i').key_up(Keys.CONTROL)
            actions.send_keys(' ')
        if element.name == 'u':
            actions.key_down(Keys.CONTROL).key_down(Keys.SHIFT).send_keys('u').key_up(Keys.SHIFT).key_up(Keys.CONTROL)
            actions.send_keys(' ')

    for tag in soup.find_all(recursive=False):
        if tag.name in ['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']:
            send_text_with_formatting(tag, actions)
            actions.send_keys(Keys.ENTER)
        elif tag.name == 'ul':
            for li in tag.find_all('li', recursive=False):
                actions.send_keys('• ')
                send_text_with_formatting(li, actions)
                actions.send_keys(Keys.ENTER)
        elif tag.name == 'ol':
            for idx, li in enumerate(tag.find_all('li', recursive=False), 1):
                actions.send_keys(f"{idx}. ")
                send_text_with_formatting(li, actions)
                actions.send_keys(Keys.ENTER)

    actions.perform()
    print("✅ Форматированный контент вставлен через горячие клавиши")

def insert_html_via_innerhtml(driver, html):
    try:
        editor = WebDriverWait(driver, 15).until(
            EC.element_to_be_clickable((By.XPATH, "/html/body/div[2]/div[2]/div[1]/div[2]/div[2]/div[2]/div/div[2]/div[1]/div/div/div/div/div/div"))
        )
        editor.click()
        time.sleep(1)

        driver.execute_script("""
            const editor = arguments[0];
            editor.focus();
            editor.innerHTML += arguments[1];
            const event = new Event('input', { bubbles: true });
            editor.dispatchEvent(event);
        """, editor, html)

        print("✅ HTML вставлен через innerHTML")
    except Exception as e:
        print(f"❌ Не удалось вставить HTML: {e}")
        
# === Drag-and-drop изображения через JS (без окна проводника) ===
def insert_cover_image(driver, folder_path, debug_html_path="debug_cover_upload.html"):
    try:
        image_files = [f for f in os.listdir(folder_path) if f.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp'))]
        if not image_files:
            print("❌ Нет изображений в папке")
            return False

        random_image = random.choice(image_files)
        image_path = os.path.join(folder_path, random_image)
        _, ext = os.path.splitext(random_image)
        ext = ext.lower().replace('.', '')
        mime_types = {
            'jpg': 'image/jpeg',
            'jpeg': 'image/jpeg',
            'png': 'image/png',
            'gif': 'image/gif',
            'bmp': 'image/bmp',
        }
        mime_type = mime_types.get(ext, 'image/jpeg')

        print(f"🖼️ Выбрано изображение: {image_path} с mime_type={mime_type}")

        insert_image_button = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, '//button[@data-tip="Вставить изображение"]'))
        )
        insert_image_button.click()
        time.sleep(1)

        drop_zone = WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.CSS_SELECTOR, '.article-editor-desktop--image-popup__dragArea-3o'))
        )
        print("🎯 Drop zone найдена")

        with open(image_path, "rb") as f:
            encoded_string = base64.b64encode(f.read()).decode("utf-8")

        js_script = """
            const base64 = arguments[0];
            const filename = arguments[1];
            const dropZone = arguments[2];
            const mimeType = arguments[3];

            const bstr = atob(base64);
            let n = bstr.length;
            const u8arr = new Uint8Array(n);
            while(n--){
                u8arr[n] = bstr.charCodeAt(n);
            }
            const blob = new Blob([u8arr], { type: mimeType });
            const file = new File([blob], filename, { type: mimeType });
            const dataTransfer = new DataTransfer();
            dataTransfer.items.add(file);

            function fireDragEvent(eventName, target, dataTransfer) {
                const event = new DragEvent(eventName, {
                    dataTransfer: dataTransfer,
                    bubbles: true,
                    cancelable: true,
                    composed: true
                });
                target.dispatchEvent(event);
            }

            fireDragEvent('dragenter', dropZone, dataTransfer);
            fireDragEvent('dragover', dropZone, dataTransfer);
            fireDragEvent('drop', dropZone, dataTransfer);
        """

        driver.execute_script(js_script, encoded_string, random_image, drop_zone, mime_type)
        print("📁 События dragenter, dragover, drop выполнены")

        time.sleep(3)

        # Проверка на ошибки, загрузка, закрытие и т.д. — ваша логика тут без изменений

        return True

    except Exception as e:
        print(f"❌ Ошибка при drag-and-drop: {e}")
        return False        
    
# === Основная функция ===
def main():
    client, profile_id = start_kameleo_profile(profile_name="Dzen_test")
    driver = init_kameleo_selenium(profile_id)

    article = get_article_from_db()
    if not article:
        print("❌ Не удалось получить статью из базы")
        driver.quit()
        client.profile.stop_profile(profile_id)
        return

    soup = BeautifulSoup(article['content'], "html.parser")
    title = extract_title_from_first_p(soup)

    if soup.body:
        cleaned_article = ''.join(str(tag) for tag in soup.body.contents if tag.name not in ['script', 'style'])
    else:
        cleaned_article = ''.join(str(tag) for tag in soup.contents if tag.name not in ['script', 'style'])

    with open("formatted_article.html", "w", encoding="utf-8") as f:
        f.write(cleaned_article)

    if not open_editor(driver):
        driver.quit()
        return
    if not create_new_article(driver):
        driver.quit()
        return

    close_tips(driver)
    insert_title(driver, title)

    insert_cover_image(driver, IMAGE_FOLDER)

    # Ждем закрытия модального окна с загрузкой картинки
    try:
        WebDriverWait(driver, 20).until(
            EC.invisibility_of_element_located((By.CSS_SELECTOR, '.article-editor-desktop--image-popup__dragArea-3o'))
        )
        print("✅ Модальное окно вставки изображения закрыто")
    except TimeoutException:
        print("❌ Модальное окно вставки изображения не закрылось вовремя")

    # Пауза для надежности
    time.sleep(2)

    #send_formatted_content(driver, cleaned_article)
    insert_html_via_innerhtml(driver, cleaned_article)
    
    input("✅ Нажмите Enter, чтобы закрыть браузер...")
    driver.quit()
    client.profile.stop_profile(profile_id)

if __name__ == "__main__":
    main() проанализируй скрипт. данные вставляются но теряется разметка html. предложи решение