import os
import sys
import logging
import configparser
from pathlib import Path
from typing import List, Dict, Optional
import requests
from docx import Document
import re

try:
    import win32com.client
    import pythoncom
except ImportError:
    win32com = None

# Настройка логирования
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[
        logging.StreamHandler(sys.stdout),
        logging.FileHandler("automation.log", encoding='utf-8')
    ]
)
logger = logging.getLogger(__name__)

def load_config(config_path: str) -> Dict[str, str]:
    config = configparser.ConfigParser()
    if not os.path.exists(config_path):
        logger.critical(f"Файл конфигурации '{config_path}' не найден.")
        sys.exit(1)
    config.read(config_path, encoding='utf-8')
    try:
        openrouter_api_key = config['API']['openrouter_api_key']
        openrouter_endpoint = config['API']['openrouter_endpoint']
        if not openrouter_api_key or not openrouter_endpoint:
            raise ValueError
        logger.info("API-ключ и эндпоинт OpenRouter успешно загружены из конфигурации.")
        return {
            "api_key": openrouter_api_key,
            "endpoint": openrouter_endpoint
        }
    except (KeyError, ValueError):
        logger.critical("API-ключ или эндпоинт OpenRouter не найдены в файле конфигурации.")
        sys.exit(1)

def read_doc(file_path: Path) -> str:
    if win32com is None:
        logger.error("Модуль win32com не установлен. Невозможно прочитать файл .doc")
        return ""
    
    pythoncom.CoInitialize()
    word = win32com.client.Dispatch("Word.Application")
    doc = word.Documents.Open(str(file_path))
    text = doc.Content.Text
    doc.Close()
    word.Quit()
    return text

def read_file(file_path: Path) -> str:
    try:
        if file_path.suffix.lower() == '.docx':
            document = Document(file_path)
            text = "\n".join([para.text for para in document.paragraphs])
        elif file_path.suffix.lower() == '.doc':
            text = read_doc(file_path)
        else:
            with open(file_path, 'r', encoding='utf-8') as file:
                text = file.read()
        logger.debug(f"Файл '{file_path}' успешно прочитан.")
        return text
    except Exception as e:
        logger.error(f"Ошибка при чтении файла '{file_path}': {e}")
        return ""

def get_file(directory: Path, keywords: List[str]) -> Optional[Path]:
    for file in directory.iterdir():
        if file.is_file() and any(keyword.lower() in file.name.lower() for keyword in keywords):
            logger.info(f"Найден файл: {file}")
            return file
    logger.warning(f"Файл с ключевыми словами {keywords} не найден в директории '{directory}'")
    return None

def list_directory_contents(directory: Path):
    logger.info(f"Содержимое директории '{directory}':")
    for item in directory.iterdir():
        logger.info(f"  {item.name}")

def parse_course_plan(plan_text: str) -> Dict[str, List[str]]:
    modules = {}
    current_module = None
    for line in plan_text.split('\n'):
        if line.strip().startswith("Модуль"):
            current_module = line.strip()
            modules[current_module] = []
        elif current_module and line.strip():
            modules[current_module].append(line.strip())
    return modules

def generate_content(api_key: str, endpoint: str, prompt: str, model: str = "anthropic/claude-3-sonnet", max_tokens: int = 4000, temperature: float = 0.7) -> Dict:
    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }
    payload = {
        "model": model,
        "messages": [{"role": "user", "content": prompt}],
        "max_tokens": max_tokens,
        "temperature": temperature
    }
    try:
        response = requests.post(endpoint, headers=headers, json=payload, timeout=30)
        response.raise_for_status()
        data = response.json()
        logger.debug("Контент успешно сгенерирован.")
        return {
            "content": data.get('choices', [{}])[0].get('message', {}).get('content', '').strip(),
            "finish_reason": data.get('choices', [{}])[0].get('finish_reason', '')
        }
    except requests.exceptions.HTTPError as e:
        if e.response.status_code == 401:
            logger.error("Ошибка авторизации. Проверьте правильность API-ключа.")
        else:
            logger.error(f"HTTP ошибка при запросе к OpenRouter API: {e}")
        return {"content": "", "finish_reason": "error"}
    except requests.exceptions.RequestException as e:
        logger.error(f"Ошибка при запросе к OpenRouter API: {e}")
        return {"content": "", "finish_reason": "error"}

def save_docx(content: str, file_path: Path) -> None:
    try:
        document = Document()
        for line in content.split('\n'):
            document.add_paragraph(line)
        document.save(file_path)
        logger.info(f"Сохранено: '{file_path}'")
    except Exception as e:
        logger.error(f"Ошибка при сохранении файла '{file_path}': {e}")

def load_instructions(instructions_dir: Path) -> str:
    instructions = ""
    instruction_files = [
        get_file(instructions_dir, ["правила", "написания", "лекции"]),
        get_file(instructions_dir, ["корректное", "отображение", "формул"])
    ]
    for file in instruction_files:
        if file:
            instructions += read_file(file) + "\n\n"
    if not instructions:
        logger.warning("Файлы инструкций не найдены.")
    return instructions.strip()

def generate_lecture(api_key: str, endpoint: str, lecture_request: str, course_plan: str, instructions: str, lecture_name: str, is_continuation: bool = False) -> str:
    prompt = f"""Запрос на написание лекции:
{lecture_request}

План курса:
{course_plan}

Инструкции:
{instructions}

{'Продолжите написание лекции:' if is_continuation else 'Напишите лекцию:'} {lecture_name}
"""
    response = generate_content(api_key, endpoint, prompt)
    return response["content"]

def generate_test(api_key: str, endpoint: str, test_request: str, module_content: str, is_final: bool = False) -> str:
    prompt = f"""Запрос на написание {'итогового' if is_final else ''} теста:
{test_request}

{'Содержание модуля:' if not is_final else 'Содержание курса:'}
{module_content}

Напишите {'итоговый' if is_final else ''} тест.
"""
    response = generate_content(api_key, endpoint, prompt)
    return response["content"]

def main():
    base_dir = Path(__file__).parent.resolve()
    input_dir = base_dir / "Входные данные"
    output_dir = base_dir / "Папка с готовыми лекциями"
    config_path = base_dir / "config.ini"

    if not input_dir.exists():
        logger.critical(f"Директория '{input_dir}' не существует.")
        sys.exit(1)

    list_directory_contents(input_dir)

    config = load_config(str(config_path))
    api_key = config["api_key"]
    endpoint = config["endpoint"]

    # Используем новую функцию get_file для поиска файлов
    lecture_request_file = get_file(input_dir, ["запрос", "написание", "лекции"])
    course_plan_file = get_file(input_dir, ["план", "курса", "лекций"])
    test_request_file = get_file(input_dir, ["запрос", "написание", "теста"])

    if not course_plan_file:
        logger.critical("Файл с планом курса не найден. Завершение работы.")
        sys.exit(1)

    if not lecture_request_file:
        logger.warning("Файл с запросом на написание лекции не найден. Будет использован файл с запросом на написание теста.")
        lecture_request_file = test_request_file

    if not test_request_file:
        logger.critical("Файл с запросом на написание теста не найден. Завершение работы.")
        sys.exit(1)

    lecture_request = read_file(lecture_request_file) if lecture_request_file else ""
    course_plan = read_file(course_plan_file)
    instructions = load_instructions(input_dir)
    test_request = read_file(test_request_file)

    modules = parse_course_plan(course_plan)

    if not modules:
        logger.critical("Не удалось разобрать план курса. Завершение работы.")
        sys.exit(1)

    for module, lectures in modules.items():
        module_dir = output_dir / module
        module_dir.mkdir(parents=True, exist_ok=True)
        module_content = ""

        for lecture in lectures:
            lecture_content = generate_lecture(api_key, endpoint, lecture_request, course_plan, instructions, lecture)
            if not lecture_content:
                logger.error(f"Не удалось сгенерировать контент для лекции '{lecture}'. Пропуск.")
                continue
            
            lecture_filename = f"{lecture}.docx"
            save_docx(lecture_content, module_dir / lecture_filename)
            module_content += lecture_content + "\n\n"

            # Если лекция не закончена, продолжаем написание
            while "продолжение следует" in lecture_content.lower():
                lecture_content = generate_lecture(api_key, endpoint, lecture_request, course_plan, instructions, lecture, True)
                if not lecture_content:
                    logger.error(f"Не удалось сгенерировать продолжение для лекции '{lecture}'. Пропуск.")
                    break
                lecture_filename = f"{lecture} (Продолжение).docx"
                save_docx(lecture_content, module_dir / lecture_filename)
                module_content += lecture_content + "\n\n"

        # Генерация теста для модуля
        module_test = generate_test(api_key, endpoint, test_request, module_content)
        if module_test:
            save_docx(module_test, module_dir / f"Тест {module}.docx")
        else:
            logger.error(f"Не удалось сгенерировать тест для модуля '{module}'.")

    # Генерация итогового теста
    final_test_dir = output_dir / "Итоговый тест"
    final_test_dir.mkdir(parents=True, exist_ok=True)
    full_course_content = "\n\n".join([read_file(file) for file in output_dir.rglob("*.docx") if "Тест" not in file.name])
    final_test = generate_test(api_key, endpoint, test_request, full_course_content, True)
    if final_test:
        save_docx(final_test, final_test_dir / "Итоговый тест.docx")
    else:
        logger.error("Не удалось сгенерировать итоговый тест.")

    logger.info("Автоматизация завершена.")

if __name__ == "__main__":
    main() посоветуй чтобы не грузить всё в конттекст в этом скрипте может добавть постую базу данных скуаль лайт ?