use teloxide::types::{Message, MessageEntity, MessageEntityKind};

/// Восстанавливает HTML разметку из entities сообщения
pub fn restore_html_from_entities(msg: &Message) -> Option<String> {
    let text = msg.text()?;
    let entities = msg.entities()?;
    
    if entities.is_empty() {
        return Some(text.to_string());
    }
    
    // Конвертируем текст в вектор символов для безопасной работы с индексами
    let chars: Vec<char> = text.chars().collect();
    let mut result = String::new();
    let mut last_end = 0;
    
    // Сортируем entities по позиции начала
    let mut sorted_entities: Vec<_> = entities.iter().collect();
    sorted_entities.sort_by_key(|e| e.offset);
    
    for entity in sorted_entities {
        // Добавляем текст до начала entity
        if entity.offset > last_end {
            let start_char = last_end;
            let end_char = entity.offset.min(chars.len());
            result.push_str(&chars[start_char..end_char].iter().collect::<String>());
        }
        
        // Добавляем текст с HTML разметкой в зависимости от типа entity
        let start_char = entity.offset;
        let end_char = (entity.offset + entity.length).min(chars.len());
        let entity_text: String = chars[start_char..end_char].iter().collect();
        
        let marked_text = match &entity.kind {
            MessageEntityKind::Bold => format!("<b>{}</b>", entity_text),
            MessageEntityKind::Italic => format!("<i>{}</i>", entity_text),
            MessageEntityKind::Code => format!("<code>{}</code>", entity_text),
            MessageEntityKind::Pre { .. } => format!("<pre>{}</pre>", entity_text),
            MessageEntityKind::TextLink { url } => format!("<a href=\"{}\">{}</a>", url, entity_text),
            MessageEntityKind::TextMention { user } => format!("<a href=\"tg://user?id={}\">{}</a>", user.id, entity_text),
            MessageEntityKind::Underline => format!("<u>{}</u>", entity_text),
            MessageEntityKind::Strikethrough => format!("<s>{}</s>", entity_text),
            MessageEntityKind::Spoiler => format!("<tg-spoiler>{}</tg-spoiler>", entity_text),
            _ => entity_text, // Для других типов просто добавляем текст
        };
        
        result.push_str(&marked_text);
        last_end = entity.offset + entity.length;
    }
    
    // Добавляем оставшийся текст
    if last_end < chars.len() {
        result.push_str(&chars[last_end..].iter().collect::<String>());
    }
    
    Some(result)
}

/// Конвертирует HTML в MarkdownV2 для отправки через Telegram API
pub fn html_to_markdown_v2(html: &str) -> String {
    let mut result = html.to_string();
    
    // Заменяем HTML теги на MarkdownV2 синтаксис
    result = result.replace("<b>", "*").replace("</b>", "*");
    result = result.replace("<i>", "_").replace("</i>", "_");
    result = result.replace("<u>", "__").replace("</u>", "__");
    result = result.replace("<s>", "~").replace("</s>", "~");
    result = result.replace("<code>", "`").replace("</code>", "`");
    result = result.replace("<pre>", "```").replace("</pre>", "```");
    result = result.replace("<tg-spoiler>", "||").replace("</tg-spoiler>", "||");
    
    // Обрабатываем ссылки
    result = regex::Regex::new(r#"<a href="([^"]+)">([^<]+)</a>"#)
        .unwrap()
        .replace_all(&result, "[$2]($1)")
        .to_string();
    
    // Экранируем специальные символы для MarkdownV2
    escape_markdown_v2(&result)
}

/// Экранирует специальные символы для MarkdownV2
pub fn escape_markdown_v2(text: &str) -> String {
    text.chars()
        .map(|c| match c {
            '_' => "\\_".to_string(),
            '*' => "\\*".to_string(),
            '[' => "\\[".to_string(),
            ']' => "\\]".to_string(),
            '(' => "\\(".to_string(),
            ')' => "\\)".to_string(),
            '~' => "\\~".to_string(),
            '`' => "\\`".to_string(),
            '>' => "\\>".to_string(),
            '#' => "\\#".to_string(),
            '+' => "\\+".to_string(),
            '-' => "\\-".to_string(),
            '=' => "\\=".to_string(),
            '{' => "\\{".to_string(),
            '}' => "\\}".to_string(),
            '.' => "\\.".to_string(),
            '!' => "\\!".to_string(),
            '|' => "\\|".to_string(),
            _ => c.to_string(),
        })
        .collect()
}

#[cfg(test)]
mod tests {
    use super::*;
    use teloxide::types::{Message, MessageEntity, MessageEntityKind, User, UserId};

    #[test]
    fn test_escape_markdown_v2() {
        assert_eq!(escape_markdown_v2("Hello *world*"), "Hello \\*world\\*");
        assert_eq!(escape_markdown_v2("Test [link](url)"), "Test \\[link\\]\\(url\\)");
    }
}
