//! 书签与标注模块
//! 
//! 支持高亮、下划线、波浪线、边注等标注类型

use anyhow::Result;
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};

/// 标注类型
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum HighlightType {
    /// 高亮线
    Highlight,
    /// 下划线
    Underline,
    /// 波浪线
    Wavy,
    /// 边注
    MarginNote,
}

/// 书签/标注记录
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Bookmark {
    /// 唯一标识
    pub id: String,
    /// 文档路径
    pub document_path: String,
    /// 页码
    pub page_number: usize,
    /// 位置偏移
    pub position: usize,
    /// 标注类型
    pub highlight_type: HighlightType,
    /// 标注的原文内容
    pub text: String,
    /// 用户笔记
    pub note: Option<String>,
    /// 颜色 (HEX)
    pub color: Option<String>,
    /// 创建时间
    pub created_at: DateTime<Utc>,
    /// 更新时间
    pub updated_at: DateTime<Utc>,
}

impl Bookmark {
    pub fn new(
        document_path: String,
        page_number: usize,
        position: usize,
        highlight_type: HighlightType,
        text: String,
    ) -> Self {
        let now = Utc::now();
        Self {
            id: uuid::Uuid::new_v4().to_string(),
            document_path,
            page_number,
            position,
            highlight_type,
            text,
            note: None,
            color: None,
            created_at: now,
            updated_at: now,
        }
    }
    
    /// 设置笔记内容
    pub fn with_note(mut self, note: String) -> Self {
        self.note = Some(note);
        self.updated_at = Utc::now();
        self
    }
    
    /// 设置颜色
    pub fn with_color(mut self, color: String) -> Self {
        self.color = Some(color);
        self.updated_at = Utc::now();
        self
    }
}

/// 书签管理器
pub struct BookmarkManager {
    db: sled::Db,
}

impl BookmarkManager {
    /// 创建书签管理器
    pub fn new(db_path: &str) -> Result<Self> {
        let db = sled::open(db_path)?;
        Ok(Self { db })
    }
    
    /// 添加书签
    pub fn add(&self, bookmark: &Bookmark) -> Result<()> {
        let key = format!("bookmark:{}", bookmark.id);
        let value = serde_json::to_vec(bookmark)?;
        self.db.insert(key, value)?;
        Ok(())
    }
    
    /// 删除书签
    pub fn remove(&self, id: &str) -> Result<()> {
        let key = format!("bookmark:{}", id);
        self.db.remove(key)?;
        Ok(())
    }
    
    /// 获取文档的所有书签
    pub fn get_by_document(&self, document_path: &str) -> Result<Vec<Bookmark>> {
        let prefix = format!("bookmark:");
        let mut bookmarks = Vec::new();
        
        for item in self.db.scan_prefix(prefix) {
            let (_, value) = item?;
            let bookmark: Bookmark = serde_json::from_slice(&value)?;
            if bookmark.document_path == document_path {
                bookmarks.push(bookmark);
            }
        }
        
        // 按页码和位置排序
        bookmarks.sort_by(|a, b| {
            a.page_number.cmp(&b.page_number)
                .then(a.position.cmp(&b.position))
        });
        
        Ok(bookmarks)
    }
    
    /// 获取所有书签
    pub fn get_all(&self) -> Result<Vec<Bookmark>> {
        let mut bookmarks = Vec::new();
        
        for item in self.db.scan_prefix("bookmark:") {
            let (_, value) = item?;
            let bookmark: Bookmark = serde_json::from_slice(&value)?;
            bookmarks.push(bookmark);
        }
        
        Ok(bookmarks)
    }
    
    /// 导出书签为 Markdown
    pub fn export_markdown(&self, document_path: &str) -> Result<String> {
        let bookmarks = self.get_by_document(document_path)?;
        let mut md = String::new();
        
        md.push_str(&format!("# {} 标注导出\n\n", document_path));
        md.push_str(&format!("导出时间：{}\n\n", Utc::now().format("%Y-%m-%d %H:%M:%S")));
        md.push_str(&format!("共 {} 处标注\n\n", bookmarks.len()));
        md.push_str("---\n\n");
        
        let mut current_page = 0;
        for bookmark in bookmarks {
            if bookmark.page_number != current_page {
                current_page = bookmark.page_number;
                md.push_str(&format!("## 第 {} 页\n\n", current_page));
            }
            
            // 标注类型图标
            let icon = match bookmark.highlight_type {
                HighlightType::Highlight => "🟨",
                HighlightType::Underline => "📏",
                HighlightType::Wavy => "〰️",
                HighlightType::MarginNote => "📝",
            };
            
            md.push_str(&format!("{} **{}**\n\n", icon, bookmark.text));
            
            if let Some(note) = &bookmark.note {
                md.push_str(&format!("> 💬 {}\n\n", note));
            }
            
            md.push_str("---\n\n");
        }
        
        Ok(md)
    }
    
    /// 导出书签为 CSV
    pub fn export_csv(&self, document_path: &str) -> Result<String> {
        let bookmarks = self.get_by_document(document_path)?;
        let mut csv = String::new();
        
        // CSV 头部
        csv.push_str("id,page,position,type,text,note,color,created_at\n");
        
        for bookmark in bookmarks {
            let highlight_type_str = match bookmark.highlight_type {
                HighlightType::Highlight => "highlight",
                HighlightType::Underline => "underline",
                HighlightType::Wavy => "wavy",
                HighlightType::MarginNote => "margin_note",
            };
            
            let note = bookmark.note.as_deref().unwrap_or("");
            let color = bookmark.color.as_deref().unwrap_or("");
            
            // CSV 转义
            let text_escaped = bookmark.text.replace('"', "\"\"");
            let note_escaped = note.replace('"', "\"\"");
            
            csv.push_str(&format!(
                "{},{},{},{},\"{}\",\"{}\",\"{}\",{}\n",
                bookmark.id,
                bookmark.page_number,
                bookmark.position,
                highlight_type_str,
                text_escaped,
                note_escaped,
                color,
                bookmark.created_at.to_rfc3339()
            ));
        }
        
        Ok(csv)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_bookmark_creation() {
        let bookmark = Bookmark::new(
            "/path/to/doc.md".to_string(),
            1,
            100,
            HighlightType::Highlight,
            "这是一段测试文本".to_string(),
        );
        
        assert_eq!(bookmark.page_number, 1);
        assert_eq!(bookmark.text, "这是一段测试文本");
    }
}
