#!/usr/bin/env python3

import re
import time
import logging
import asyncio

from config import DISCORD_CONFIG

# Discord импорты - только если Discord включен
if DISCORD_CONFIG['enabled']:
    try:
        import discord
    except ImportError:
        logging.error("Discord.py не установлен, но Discord включен в конфигурации")
        DISCORD_CONFIG['enabled'] = False


class DiscordClient:
    def __init__(self, content_processor):
        self.logger = logging.getLogger(__name__)
        self.content_processor = content_processor
        self.config = DISCORD_CONFIG
        
        if not self.config['enabled']:
            self.logger.info("Discord клиент отключен в конфигурации")
    
    async def get_messages(self, client, channel_id):
        """Получение сообщений из Discord канала"""
        if not self.is_enabled():
            return [], []
            
        self.logger.debug("Получаем сообщения из Discord канала")
        channel = client.get_channel(channel_id)
        if not channel:
            self.logger.error(f"ID канала Discord {channel_id} не существует")
            return [], []

        messages = []
        titles = []
        
        async for message in channel.history(limit=100):
            self.logger.debug(f"Сообщение Discord: {message.content}")
            messages.append(message.content)
            
            # Извлекаем заголовок из сообщения
            title = self._extract_title_from_message(message.content)
            if title:
                titles.append(title)
        
        self.logger.debug(f"Найдено {len(messages)} сообщений и {len(titles)} заголовков в Discord")
        return messages, titles
    
    def _extract_title_from_message(self, message_text):
        """Извлечение заголовка из текста сообщения"""
        if not message_text:
            return None
            
        # Ищем заголовки в формате "### Заголовок\t"
        pattern = re.compile(r'^### (.*?)\t', re.MULTILINE)
        match = pattern.search(message_text)
        if match:
            return match.group(1).strip()
        
        # Ищем заголовки в формате "------ ### Заголовок\t"
        pattern2 = re.compile(r'--+\n### (.*?)\t', re.MULTILINE)
        match2 = pattern2.search(message_text)
        if match2:
            return match2.group(1).strip()
        
        # Если не найдено, ищем в первой строке
        lines = message_text.strip().split('\n')
        if lines:
            first_line = lines[0].strip()
            # Убираем префиксы типа "###", "**", и табы
            first_line = re.sub(r'^[#*\s\t-]+', '', first_line)
            first_line = re.sub(r'\t.*$', '', first_line)
            return first_line.strip() if first_line else None
        
        return None
    
    async def send_message(self, channel, content):
        """Отправка сообщения в Discord канал с разбивкой длинных сообщений"""
        if not self.is_enabled():
            return
            
        try:
            # Discord лимит: 2000 символов
            max_length = 2000
            
            if len(content) <= max_length:
                # Короткое сообщение - отправляем как есть
                await channel.send(content)
            else:
                # Длинное сообщение - разбиваем умно по строкам
                self.logger.warning(f"Сообщение слишком длинное ({len(content)} символов), разбиваем на части")
                
                parts = []
                current_part = ""
                
                for line in content.split('\n'):
                    # Если добавление этой строки превысит лимит
                    if len(current_part + line + '\n') > max_length:
                        if current_part:
                            parts.append(current_part.rstrip())
                            current_part = ""
                    current_part += line + '\n'
                
                # Добавляем последнюю часть
                if current_part:
                    parts.append(current_part.rstrip())
                
                self.logger.info(f"Сообщение разбито на {len(parts)} частей для Discord")
                
                # Отправляем каждую часть
                for i, part in enumerate(parts, 1):
                    if len(parts) > 1:
                        part_content = f"[Часть {i}/{len(parts)}]\n\n{part}"
                    else:
                        part_content = part
                    await channel.send(part_content)
                    
                    # Небольшая задержка между частями
                    if i < len(parts):
                        await asyncio.sleep(1)
            
            self.logger.info("Сообщение успешно отправлено в Discord")
        except Exception as e:
            self.logger.error(f"Ошибка отправки сообщения в Discord: {e}")
    
    async def check_and_publish_news(self, news_list):
        """Проверка и публикация новостей в Discord"""
        if not self.is_enabled():
            self.logger.info("Discord отключен, пропускаем публикацию")
            return
            
        self.logger.info("Начинаем проверку новостей для Discord")
        
        intents = discord.Intents.default()
        intents.messages = True
        client = discord.Client(intents=intents)
        
        @client.event
        async def on_ready():
            self.logger.debug(f"Успешный логин в Discord: {client.user}")
            channel_id = self.config['channel_id']
            
            # Получаем существующие сообщения и заголовки
            discord_messages, discord_titles = await self.get_messages(client, channel_id)
            
            if not news_list:
                self.logger.warning("Список новостей пуст")
                await client.close()
                return
            
            # Фильтруем новости для публикации
            list_for_public = []
            for topic_id, topic_title in news_list:
                # Проверяем по заголовкам и по полному тексту сообщений
                title_exists = any(topic_title == title for title in discord_titles)
                text_contains = any(topic_title in (msg or '') for msg in discord_messages)
                
                if not title_exists and not text_contains:
                    list_for_public.append((topic_id, topic_title))
                else:
                    self.logger.debug(f"Новость '{topic_title}' уже есть в Discord (title_exists={title_exists}, text_contains={text_contains})")
            
            if not list_for_public:
                self.logger.warning("Новостей для публикации в Discord нет")
                await client.close()
                return
            
            self.logger.info(f"Новости для публикации в Discord: {list_for_public}")
            
            channel = client.get_channel(channel_id)
            if not channel:
                self.logger.error(f"ID канала Discord {channel_id} не существует")
                await client.close()
                return
            
            # Публикуем новости в обратном порядке, чтобы новые оказались сверху в ленте
            for topic_id, topic_title in reversed(list_for_public):
                from site_api import SiteAPI
                site_api = SiteAPI()
                text_data = site_api.get_news_content(topic_id, self.content_processor)
                
                if text_data:
                    content = f"----------------------------------------------------------\n### {topic_title}\t\n" + text_data + "\n@here"
                    await self.send_message(channel, content)
                    time.sleep(1.0)
                else:
                    self.logger.warning(f"Не удалось получить содержимое новости {topic_id}")
            
            await client.close()
        
        try:
            await client.start(self.config['token'])
        except Exception as e:
            self.logger.error(f"Ошибка запуска Discord клиента: {e}")
    
    def is_enabled(self):
        """Проверка, включен ли Discord клиент"""
        return (self.config['enabled'] and 
                self.config['token'] and 
                self.config['channel_id'])