"""
钉钉Webhook推送工具
支持推送Markdown格式消息到钉钉群
"""
import requests
import json
from typing import Optional, Dict, Any
from loguru import logger


class DingTalkWebhook:
    """钉钉Webhook推送工具"""
    
    def __init__(self, webhook_url: str):
        """
        初始化钉钉Webhook
        
        Args:
            webhook_url: 钉钉机器人Webhook地址
        """
        self.webhook_url = webhook_url
        self.logger = logger.bind(module="DingTalkWebhook")
    
    def send_text(self, content: str, at_mobiles: list = None, at_all: bool = False) -> bool:
        """
        发送文本消息
        
        Args:
            content: 消息内容
            at_mobiles: 要@的手机号列表
            at_all: 是否@所有人
            
        Returns:
            是否发送成功
        """
        data = {
            "msgtype": "text",
            "text": {
                "content": content
            }
        }
        
        if at_mobiles or at_all:
            data["at"] = {}
            if at_mobiles:
                data["at"]["atMobiles"] = at_mobiles
            if at_all:
                data["at"]["isAtAll"] = True
        
        return self._send(data)
    
    def send_markdown(self, title: str, text: str, at_mobiles: list = None, at_all: bool = False) -> bool:
        """
        发送Markdown消息
        
        Args:
            title: 消息标题
            text: Markdown内容（钉钉支持的格式）
            at_mobiles: 要@的手机号列表
            at_all: 是否@所有人
            
        Returns:
            是否发送成功
        """
        # 钉钉markdown消息有长度限制，需要截断
        max_length = 5000
        if len(text) > max_length:
            text = text[:max_length - 100] + "\n\n...（内容已截断，完整内容请查看附件）"
            self.logger.warning(f"Markdown内容过长，已截断至{max_length}字符")
        
        data = {
            "msgtype": "markdown",
            "markdown": {
                "title": title,
                "text": text
            }
        }
        
        if at_mobiles or at_all:
            data["at"] = {}
            if at_mobiles:
                data["at"]["atMobiles"] = at_mobiles
            if at_all:
                data["at"]["isAtAll"] = True
        
        return self._send(data)
    
    def send_markdown_from_file(self, title: str, markdown_file: str, 
                                 max_length: int = 5000, at_mobiles: list = None, 
                                 at_all: bool = False) -> bool:
        """
        从Markdown文件发送消息
        
        Args:
            title: 消息标题
            markdown_file: Markdown文件路径
            max_length: 最大长度限制（默认5000字符）
            at_mobiles: 要@的手机号列表
            at_all: 是否@所有人
            
        Returns:
            是否发送成功
        """
        try:
            with open(markdown_file, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 转换为钉钉markdown格式（简化一些不支持的语法）
            text = self._convert_to_dingtalk_markdown(content, max_length)
            
            return self.send_markdown(title, text, at_mobiles, at_all)
            
        except Exception as e:
            self.logger.error(f"读取Markdown文件失败: {str(e)}", exc_info=True)
            return False
    
    def _convert_to_dingtalk_markdown(self, content: str, max_length: int = 5000) -> str:
        """
        将标准Markdown转换为钉钉支持的格式
        
        钉钉Markdown支持的语法：
        - 标题：# ## ###
        - 加粗：**text**
        - 链接：[text](url)
        - 列表：- 或 1.
        - 引用：>
        - 代码：`code`
        - 换行：两个换行符
        
        不支持：
        - 表格（需要转换为文本）
        - HTML标签
        - 复杂嵌套
        """
        # 如果内容太长，截断并添加提示
        if len(content) > max_length:
            content = content[:max_length - 200] + "\n\n---\n\n**提示**: 内容已截断，完整内容请查看报告文件。"
        
        # 钉钉markdown基本兼容标准markdown，但需要清理一些不支持的语法
        # 保留基本格式即可
        text = content
        
        return text
    
    def _send(self, data: Dict[str, Any]) -> bool:
        """
        发送消息到钉钉
        
        Args:
            data: 消息数据
            
        Returns:
            是否发送成功
        """
        try:
            headers = {
                'Content-Type': 'application/json'
            }
            
            response = requests.post(
                self.webhook_url,
                headers=headers,
                data=json.dumps(data),
                timeout=10
            )
            
            response.raise_for_status()
            result = response.json()
            
            if result.get('errcode') == 0:
                self.logger.info("消息发送成功")
                return True
            else:
                self.logger.error(f"消息发送失败: {result.get('errmsg', '未知错误')}")
                return False
                
        except requests.exceptions.RequestException as e:
            self.logger.error(f"发送消息请求失败: {str(e)}", exc_info=True)
            return False
        except Exception as e:
            self.logger.error(f"发送消息失败: {str(e)}", exc_info=True)
            return False
    
    def send_report(self, title: str, markdown_content: str, markdown_file: str = None) -> bool:
        """
        发送报告消息（优化版本，自动处理长内容）
        
        Args:
            title: 消息标题
            markdown_content: Markdown内容
            markdown_file: Markdown文件路径（可选，用于提示）
            
        Returns:
            是否发送成功
        """
        # 钉钉markdown有长度限制，需要截断或分段
        max_length = 4500  # 留一些余量
        
        if len(markdown_content) <= max_length:
            # 内容不长，直接发送
            text = markdown_content
            if markdown_file:
                text += f"\n\n---\n\n**完整报告**: 已保存到 `{markdown_file}`"
            return self.send_markdown(title, text)
        else:
            # 内容太长，发送摘要
            # 提取关键部分（标题、统计、前几条新闻）
            lines = markdown_content.split('\n')
            summary_lines = []
            news_count = 0
            max_news_items = 5
            
            for line in lines:
                summary_lines.append(line)
                # 计算已添加的新闻条目数
                if line.startswith('### ') and news_count < max_news_items:
                    news_count += 1
                    # 添加接下来的几行（摘要、链接等）
                    continue
                elif news_count >= max_news_items and line.startswith('### '):
                    # 达到最大条目数，停止添加
                    break
            
            summary = '\n'.join(summary_lines)
            
            # 如果还有更多内容，添加提示
            if len(markdown_content) > len(summary):
                remaining_count = markdown_content.count('### ') - news_count
                summary += f"\n\n---\n\n**提示**: 报告内容较长，已显示前{news_count}条新闻。"
                if remaining_count > 0:
                    summary += f" 还有{remaining_count}条新闻未显示。"
                if markdown_file:
                    summary += f"\n\n**完整报告**: 已保存到 `{markdown_file}`"
            
            return self.send_markdown(title, summary)

