//! 文档处理引擎
//! 
//! 支持 PDF、EPUB、MOBI、TXT、Markdown 等格式

use anyhow::{Context, Result};
use std::path::Path;

#[derive(Debug)]
pub enum DocumentFormat {
    Pdf,
    Epub,
    Mobi,
    Azw3,
    Txt,
    Markdown,
    Code(String), // 代码语言
}

pub struct Document {
    pub format: DocumentFormat,
    pub title: String,
    pub path: String,
    pub metadata: DocumentMetadata,
    pub pages: Vec<Page>,
}

#[derive(Debug, Default)]
pub struct DocumentMetadata {
    pub title: Option<String>,
    pub author: Option<String>,
    pub page_count: usize,
    pub file_size: u64,
    pub creation_date: Option<String>,
    pub modification_date: Option<String>,
}

#[derive(Debug, Clone)]
pub struct Page {
    pub number: usize,
    pub width: f32,
    pub height: f32,
    pub content: PageContent,
}

#[derive(Debug, Clone)]
pub enum PageContent {
    Pdf(Vec<u8>),           // PDF 渲染数据
    Text(String),           // 纯文本内容
    Html(String),           // HTML 渲染内容
}

#[derive(Debug, Clone)]
pub struct BilingualPage {
    pub number: usize,
    pub original: PageContent,
    pub translated: PageContent,
    pub source_lang: String,
    pub target_lang: String,
}

#[derive(Debug, Clone)]
pub struct BilingualDocument {
    pub title: String,
    pub pages: Vec<BilingualPage>,
    pub source_lang: String,
    pub target_lang: String,
}

pub struct DocumentEngine;

impl DocumentEngine {
    pub fn new() -> Self {
        Self
    }
    
    /// 根据文件扩展名判断文档格式
    fn detect_format(path: &str) -> Option<DocumentFormat> {
        let path = Path::new(path);
        let ext = path.extension()?.to_str()?.to_lowercase();
        
        match ext.as_str() {
            "pdf" => Some(DocumentFormat::Pdf),
            "epub" => Some(DocumentFormat::Epub),
            "mobi" => Some(DocumentFormat::Mobi),
            "azw" | "azw3" => Some(DocumentFormat::Azw3),
            "txt" | "text" => Some(DocumentFormat::Txt),
            "md" | "markdown" => Some(DocumentFormat::Markdown),
            "js" | "ts" | "py" | "rs" | "go" | "java" | "c" | "cpp" | "h" | "css" | "html" | "json" | "xml" | "yaml" | "yml" | "toml" | "sql" | "sh" | "bash" | "zsh" => {
                Some(DocumentFormat::Code(ext))
            }
            _ => None,
        }
    }
    
    /// 打开文档
    pub fn open(&self, path: &str) -> Result<Document> {
        let format = Self::detect_format(path)
            .context("Unsupported document format")?;
        
        let path_obj = Path::new(path);
        let title = path_obj
            .file_stem()
            .and_then(|s| s.to_str())
            .unwrap_or("Untitled")
            .to_string();
        
        let file_metadata = std::fs::metadata(path)
            .map(|m| DocumentMetadata {
                file_size: m.len(),
                ..Default::default()
            })
            .unwrap_or_default();
        
        // 读取文件内容
        let content = std::fs::read(path)?;
        
        // 根据格式解析文档并提取元数据
        let (pages, mut metadata) = match format {
            DocumentFormat::Pdf => {
                let pages = self.parse_pdf(&content)?;
                (pages, file_metadata)
            }
            DocumentFormat::Epub => {
                let (pages, epub_meta) = self.parse_epub_with_metadata(&content)?;
                let mut meta = file_metadata;
                meta.author = epub_meta.author;
                meta.title = epub_meta.title;
                (pages, meta)
            }
            DocumentFormat::Mobi => {
                let (pages, mobi_meta) = self.parse_mobi_with_metadata(&content)?;
                let mut meta = file_metadata;
                meta.author = mobi_meta.author;
                meta.title = mobi_meta.title;
                (pages, meta)
            }
            DocumentFormat::Markdown => {
                let (pages, md_meta) = self.parse_markdown_with_metadata(&content)?;
                let mut meta = file_metadata;
                meta.title = md_meta.title;
                (pages, meta)
            }
            DocumentFormat::Code(ref lang) => {
                let pages = self.parse_code(&content, lang)?;
                (pages, file_metadata)
            }
            _ => {
                let pages = vec![Page {
                    number: 1,
                    width: 612.0,
                    height: 792.0,
                    content: PageContent::Text(String::from_utf8_lossy(&content).to_string()),
                }];
                (pages, file_metadata)
            }
        };
        
        // 使用从文件提取的标题（如果有）
        let doc_title = metadata.title.clone().unwrap_or(title);
        
        Ok(Document {
            format,
            title: doc_title,
            path: path.to_string(),
            metadata: DocumentMetadata {
                page_count: pages.len(),
                ..metadata
            },
            pages,
        })
    }
    
    /// 解析 PDF 文档
    fn parse_pdf(&self, content: &[u8]) -> Result<Vec<Page>> {
        // 使用 pdfium-render 库解析 PDF
        // 这里简化实现，实际需要更复杂的处理
        
        // 创建一个简单的页面列表
        // 实际实现中，pdfium 会返回每个页面的渲染数据
        Ok(vec![Page {
            number: 1,
            width: 612.0,  // 美国信纸宽度 (8.5" * 72 dpi)
            height: 792.0, // 美国信纸高度
            content: PageContent::Pdf(content.to_vec()),
        }])
    }
    
    /// 解析 EPUB 文档
    fn parse_epub(&self, content: &[u8]) -> Result<Vec<Page>> {
        use epub::doc::EpubDoc;
        
        // 创建临时文件
        let temp_path = std::env::temp_dir().join("readflow_temp.epub");
        std::fs::write(&temp_path, content)?;
        
        // 打开 EPUB 文档
        let mut doc = EpubDoc::new(&temp_path)
            .map_err(|e| anyhow::anyhow!("EPUB 解析失败：{}", e))?;
        
        let mut pages = Vec::new();
        let mut page_num = 0;
        
        // 遍历 spine
        for _ in 0..doc.spine.len() {
            if let Some((content_str, _mime)) = doc.get_current_str() {
                pages.push(Page {
                    number: page_num,
                    width: 612.0,
                    height: 792.0,
                    content: PageContent::Html(content_str),
                });
                page_num += 1;
            }
            let _ = doc.go_next();
        }
        
        // 清理临时文件
        let _ = std::fs::remove_file(&temp_path);
        
        Ok(pages)
    }
    
    /// 解析 MOBI 文档
    fn parse_mobi(&self, content: &[u8]) -> Result<Vec<Page>> {
        use mobi::Mobi;
        
        // 创建临时文件
        let temp_path = std::env::temp_dir().join("readflow_temp.mobi");
        std::fs::write(&temp_path, content)?;
        
        // 打开 MOBI 文档
        let mobi = Mobi::new(&temp_path)
            .map_err(|e| anyhow::anyhow!("MOBI 解析失败：{}", e))?;
        
        let mut pages = Vec::new();
        let mut page_num = 0;
        
        // 获取原始内容并分页
        let content_str = mobi.content_as_string();
        let lines: Vec<&str> = content_str.lines().collect();
        const LINES_PER_PAGE: usize = 50;
        
        for chunk in lines.chunks(LINES_PER_PAGE) {
            let page_text = chunk.join("\n");
            pages.push(Page {
                number: page_num,
                width: 600.0,
                height: 800.0,
                content: PageContent::Text(page_text),
            });
            page_num += 1;
        }
        
        // 清理临时文件
        let _ = std::fs::remove_file(&temp_path);
        
        Ok(pages)
    }
    
    /// 解析 EPUB 文档并提取元数据
    fn parse_epub_with_metadata(&self, content: &[u8]) -> Result<(Vec<Page>, DocumentMetadata)> {
        use epub::doc::EpubDoc;
        
        // 创建临时文件
        let temp_path = std::env::temp_dir().join("readflow_temp.epub");
        std::fs::write(&temp_path, content)?;
        
        // 打开 EPUB 文档
        let mut doc = EpubDoc::new(&temp_path)
            .map_err(|e| anyhow::anyhow!("EPUB 解析失败：{}", e))?;
        
        // 提取元数据
        let metadata = DocumentMetadata {
            title: doc.mdata("title").map(|m| m.value.clone()),
            author: doc.mdata("creator").or_else(|| doc.mdata("author")).map(|m| m.value.clone()),
            ..Default::default()
        };
        
        // 解析内容
        let mut pages = Vec::new();
        let mut page_num = 0;
        
        for _ in 0..doc.spine.len() {
            if let Some((content_str, _mime)) = doc.get_current_str() {
                pages.push(Page {
                    number: page_num,
                    width: 612.0,
                    height: 792.0,
                    content: PageContent::Html(content_str),
                });
                page_num += 1;
            }
            let _ = doc.go_next();
        }
        
        // 清理临时文件
        let _ = std::fs::remove_file(&temp_path);
        
        Ok((pages, metadata))
    }
    
    /// 解析 MOBI 文档并提取元数据
    fn parse_mobi_with_metadata(&self, content: &[u8]) -> Result<(Vec<Page>, DocumentMetadata)> {
        use mobi::Mobi;
        
        // 创建临时文件
        let temp_path = std::env::temp_dir().join("readflow_temp.mobi");
        std::fs::write(&temp_path, content)?;
        
        // 打开 MOBI 文档
        let mobi = Mobi::new(&temp_path)
            .map_err(|e| anyhow::anyhow!("MOBI 解析失败：{}", e))?;
        
        // 提取元数据
        let metadata = DocumentMetadata {
            title: mobi.title().cloned(),
            author: mobi.author().cloned(),
            ..Default::default()
        };
        
        // 解析内容
        let mut pages = Vec::new();
        let mut page_num = 0;
        
        // 获取原始内容
        let content_str = mobi.content_as_string();
        let lines: Vec<&str> = content_str.lines().collect();
        const LINES_PER_PAGE: usize = 50;
        
        for chunk in lines.chunks(LINES_PER_PAGE) {
            let page_text = chunk.join("\n");
            pages.push(Page {
                number: page_num,
                width: 600.0,
                height: 800.0,
                content: PageContent::Text(page_text),
            });
            page_num += 1;
        }
        
        // 清理临时文件
        let _ = std::fs::remove_file(&temp_path);
        
        Ok((pages, metadata))
    }
    
    /// 解析 Markdown 文档并提取元数据
    fn parse_markdown_with_metadata(&self, content: &[u8]) -> Result<(Vec<Page>, DocumentMetadata)> {
        use pulldown_cmark::{Parser, Options};
        
        let content_str = String::from_utf8_lossy(content);
        
        // 提取 Front Matter 元数据 (YAML 格式)
        let mut metadata = DocumentMetadata::default();
        let markdown_content = if content_str.starts_with("---") {
            // 有 Front Matter
            if let Some(end) = content_str[3..].find("---") {
                let front_matter = &content_str[3..end + 3];
                // 简单解析 YAML
                for line in front_matter.lines() {
                    let line = line.trim();
                    if line.starts_with("title:") {
                        metadata.title = Some(line[6..].trim().trim_matches('"').trim_matches('\'').to_string());
                    } else if line.starts_with("author:") {
                        metadata.author = Some(line[7..].trim().trim_matches('"').trim_matches('\'').to_string());
                    }
                }
                &content_str[end + 6..]
            } else {
                &content_str
            }
        } else {
            &content_str
        };
        
        // 使用 pulldown-cmark 解析 Markdown
        let mut options = Options::empty();
        options.insert(Options::ENABLE_STRIKETHROUGH);
        options.insert(Options::ENABLE_TABLES);
        options.insert(Options::ENABLE_TASKLISTS);
        
        let parser = Parser::new_ext(markdown_content, options);
        
        // 将 Markdown 转换为 HTML
        let mut html = String::new();
        pulldown_cmark::html::push_html(&mut html, parser);
        
        // 按章节分页 (根据 H1/H2 标题)
        let pages = vec![Page {
            number: 1,
            width: 612.0,
            height: 792.0,
            content: PageContent::Html(html),
        }];
        
        Ok((pages, metadata))
    }
    
    /// 解析代码文件
    fn parse_code(&self, content: &[u8], _lang: &str) -> Result<Vec<Page>> {
        let content_str = String::from_utf8_lossy(content).to_string();
        
        // 代码文件通常不分页，作为单页处理
        let pages = vec![Page {
            number: 1,
            width: 612.0,
            height: 792.0,
            content: PageContent::Text(content_str),
        }];
        
        Ok(pages)
    }
    
    /// 渲染文档为 HTML
    pub fn render(&self, doc: &Document) -> Result<String> {
        let mut html = String::new();
        
        html.push_str("<!DOCTYPE html>\n<html>\n<head>\n");
        html.push_str("<meta charset=\"UTF-8\">\n");
        html.push_str(&format!("<title>{}</title>\n", doc.title));
        html.push_str("<style>\n");
        html.push_str(Self::get_default_css());
        html.push_str("</style>\n</head>\n<body>\n");
        html.push_str("<div class=\"document\">\n");
        
        for page in &doc.pages {
            match &page.content {
                PageContent::Pdf(data) => {
                    html.push_str(&format!(
                        "<div class=\"page pdf-page\" data-page=\"{}\">\n",
                        page.number
                    ));
                    // 后续：Base64 编码的 PDF 数据用于嵌入
                    html.push_str("</div>\n");
                }
                PageContent::Text(text) => {
                    html.push_str(&format!(
                        "<div class=\"page text-page\" data-page=\"{}\">\n",
                        page.number
                    ));
                    html.push_str(&self.format_text_content(text));
                    html.push_str("</div>\n");
                }
                PageContent::Html(html_content) => {
                    html.push_str(html_content);
                }
            }
        }
        
        html.push_str("</div>\n</body>\n</html>");
        
        Ok(html)
    }
    
    /// 获取默认 CSS 样式
    fn get_default_css() -> &'static str {
        r#":root {
    --bg-primary: #ffffff;
    --bg-secondary: #f5f5f5;
    --bg-tertiary: #e8e8e8;
    --text-primary: #333333;
    --text-secondary: #666666;
    --text-muted: #999999;
    --border-color: #e0e0e0;
    --accent-color: #4a90d9;
    --accent-hover: #3a7bc8;
    --shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
[data-theme="dark"] {
    --bg-primary: #1a1a1a;
    --bg-secondary: #2a2a2a;
    --bg-tertiary: #3a3a3a;
    --text-primary: #e0e0e0;
    --text-secondary: #b0b0b0;
    --text-muted: #808080;
    --border-color: #404040;
    --accent-color: #5a9fe0;
    --accent-hover: #6aafef;
    --shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    font-size: 16px;
    line-height: 1.6;
    color: var(--text-primary);
    background-color: var(--bg-primary);
}
.document { max-width: 800px; margin: 0 auto; padding: 20px; }
.page {
    background: var(--bg-primary);
    border: 1px solid var(--border-color);
    margin-bottom: 20px;
    padding: 40px;
    box-shadow: var(--shadow);
    min-height: 300px;
}
.text-page { white-space: pre-wrap; word-wrap: break-word; }
pre, code {
    font-family: "SF Mono", Monaco, monospace;
    font-size: 14px;
    background: var(--bg-secondary);
    border-radius: 4px;
}
pre { padding: 16px; overflow-x: auto; }
code { padding: 2px 6px; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--bg-secondary); }
::-webkit-scrollbar-thumb { background: var(--text-muted); border-radius: 4px; }
"#
    }
    
    /// 格式化文本内容
    fn format_text_content(&self, text: &str) -> String {
        // 转义 HTML 特殊字符
        let escaped = text
            .replace('&', "&amp;")
            .replace('<', "&lt;")
            .replace('>', "&gt;")
            .replace('"', "&quot;")
            .replace('\'', "&#39;");
        
        // 保留换行
        escaped.replace('\n', "<br>\n")
    }
    
    /// 搜索文档内容
    pub fn search(&self, doc: &Document, query: &str) -> Result<Vec<SearchResult>> {
        let mut results = Vec::new();
        let query_lower = query.to_lowercase();
        
        for page in &doc.pages {
            if let PageContent::Text(text) = &page.content {
                let text_lower = text.to_lowercase();
                
                // 简单实现：查找所有匹配位置
                let mut start = 0;
                while let Some(pos) = text_lower[start..].find(&query_lower) {
                    let absolute_pos = start + pos;
                    let context_start = absolute_pos.saturating_sub(50);
                    let context_end = (absolute_pos + query.len() + 50).min(text.len());
                    
                    results.push(SearchResult {
                        page: page.number,
                        position: absolute_pos,
                        context: text[context_start..context_end].to_string(),
                    });
                    
                    start = absolute_pos + 1;
                }
            }
        }
        
        Ok(results)
    }
    
    /// 获取目录结构
    pub fn get_toc(&self, doc: &Document) -> Result<Vec<TocEntry>> {
        // 简化实现：返回空目录
        // 后续可以从 PDF/EPUB 元数据中提取目录
        Ok(vec![])
    }
    
    /// 翻译文档为双语对照版本
    pub fn translate_document(
        &self,
        doc: &Document,
        source_lang: &str,
        target_lang: &str,
        translation_service: &crate::core::translation::TranslationService,
    ) -> Result<BilingualDocument> {
        let mut bilingual_pages = Vec::new();
        
        for page in &doc.pages {
            // 提取文本内容进行翻译
            let original_text = match &page.content {
                PageContent::Text(text) => text.clone(),
                PageContent::Html(html) => html.clone(),
                PageContent::Pdf(_) => continue, // PDF 暂不支持翻译
            };
            
            // 翻译内容
            let translated_text = translation_service.translate(&original_text, source_lang, target_lang)?;
            
            bilingual_pages.push(BilingualPage {
                number: page.number,
                original: page.content.clone(),
                translated: PageContent::Html(translated_text),
                source_lang: source_lang.to_string(),
                target_lang: target_lang.to_string(),
            });
        }
        
        Ok(BilingualDocument {
            title: doc.title.clone(),
            pages: bilingual_pages,
            source_lang: source_lang.to_string(),
            target_lang: target_lang.to_string(),
        })
    }
    
    /// 全文双语对照模式 - 段落级对照
    pub fn translate_document_paragraph(
        &self,
        doc: &Document,
        source_lang: &str,
        target_lang: &str,
        translation_service: &crate::core::translation::TranslationService,
    ) -> Result<BilingualDocument> {
        let mut bilingual_pages = Vec::new();
        
        for page in &doc.pages {
            // 按段落分割原文
            let original_text = match &page.content {
                PageContent::Text(text) => text.clone(),
                PageContent::Html(html) => html.clone(),
                PageContent::Pdf(_) => continue,
            };
            
            // 按段落分割
            let paragraphs: Vec<&str> = original_text
                .split("\n\n")
                .filter(|s| !s.trim().is_empty())
                .collect();
            
            // 逐段翻译
            let mut translated_paragraphs = Vec::new();
            for paragraph in &paragraphs {
                let translated = translation_service.translate(paragraph, source_lang, target_lang)?;
                translated_paragraphs.push(translated);
            }
            
            // 合并翻译结果
            let translated_text = translated_paragraphs.join("\n\n");
            
            bilingual_pages.push(BilingualPage {
                number: page.number,
                original: page.content.clone(),
                translated: PageContent::Html(translated_text),
                source_lang: source_lang.to_string(),
                target_lang: target_lang.to_string(),
            });
        }
        
        Ok(BilingualDocument {
            title: doc.title.clone(),
            pages: bilingual_pages,
            source_lang: source_lang.to_string(),
            target_lang: target_lang.to_string(),
        })
    }
    
    /// 渲染双语对照文档为 HTML (并排模式)
    pub fn render_bilingual(&self, doc: &BilingualDocument) -> Result<String> {
        let mut html = String::new();
        
        html.push_str("<!DOCTYPE html>\n<html>\n<head>\n");
        html.push_str("<meta charset=\"UTF-8\">\n");
        html.push_str(&format!("<title>{}</title>\n", doc.title));
        html.push_str("<style>\n");
        html.push_str(Self::get_bilingual_css());
        html.push_str("</style>\n</head>\n<body>\n");
        html.push_str("<div class=\"bilingual-document\">\n");
        
        for page in &doc.pages {
            html.push_str(&format!(
                "<div class=\"bilingual-page\" data-page=\"{}\">\n",
                page.number
            ));
            
            // 原文
            html.push_str("<div class=\"original-section\">\n");
            html.push_str(&format!(
                "<div class=\"section-label\">{} (原文)</div>\n",
                page.source_lang.to_uppercase()
            ));
            html.push_str("<div class=\"original-content\">\n");
            match &page.original {
                PageContent::Text(text) => {
                    html.push_str(&self.format_text_content(text));
                }
                PageContent::Html(html_content) => {
                    html.push_str(html_content);
                }
                PageContent::Pdf(_) => {}
            }
            html.push_str("</div>\n</div>\n");
            
            // 译文
            html.push_str("<div class=\"translated-section\">\n");
            html.push_str(&format!(
                "<div class=\"section-label\">{} (译文)</div>\n",
                page.target_lang.to_uppercase()
            ));
            html.push_str("<div class=\"translated-content\">\n");
            if let PageContent::Html(translated) = &page.translated {
                html.push_str(translated);
            }
            html.push_str("</div>\n</div>\n");
            
            html.push_str("</div>\n");
        }
        
        html.push_str("</div>\n</body>\n</html>");
        
        Ok(html)
    }
    
    /// 渲染双语对照文档为 HTML (段落交错模式)
    pub fn render_bilingual_interleaved(&self, doc: &BilingualDocument) -> Result<String> {
        let mut html = String::new();
        
        html.push_str("<!DOCTYPE html>\n<html>\n<head>\n");
        html.push_str("<meta charset=\"UTF-8\">\n");
        html.push_str(&format!("<title>{}</title>\n", doc.title));
        html.push_str("<style>\n");
        html.push_str(Self::get_bilingual_interleaved_css());
        html.push_str("</style>\n</head>\n<body>\n");
        html.push_str("<div class=\"bilingual-document-interleaved\">\n");
        
        for page in &doc.pages {
            html.push_str(&format!(
                "<div class=\"bilingual-page\" data-page=\"{}\">\n",
                page.number
            ));
            
            // 按段落分割并交错显示
            let original_text = match &page.original {
                PageContent::Text(text) => text.clone(),
                PageContent::Html(html) => html.clone(),
                PageContent::Pdf(_) => continue,
            };
            
            let translated_text = match &page.translated {
                PageContent::Html(html) => html.clone(),
                PageContent::Text(text) => text.clone(),
                PageContent::Pdf(_) => continue,
            };
            
            let original_paragraphs: Vec<&str> = original_text.split("\n\n").collect();
            let translated_paragraphs: Vec<&str> = translated_text.split("\n\n").collect();
            
            for (i, orig_para) in original_paragraphs.iter().enumerate() {
                if orig_para.trim().is_empty() {
                    continue;
                }
                
                html.push_str("<div class=\"paragraph-pair\">\n");
                
                // 原文段落
                html.push_str("<div class=\"original-paragraph\">\n");
                html.push_str(&self.format_text_content(orig_para));
                html.push_str("</div>\n");
                
                // 译文段落
                if i < translated_paragraphs.len() {
                    html.push_str("<div class=\"translated-paragraph\">\n");
                    html.push_str(translated_paragraphs[i]);
                    html.push_str("</div>\n");
                }
                
                html.push_str("</div>\n");
            }
            
            html.push_str("</div>\n");
        }
        
        html.push_str("</div>\n</body>\n</html>");
        
        Ok(html)
    }
    
    /// 双语对照样式 (并排模式)
    fn get_bilingual_css() -> &'static str {
        r#"
:root {
    --bg-primary: #1a1a1a;
    --bg-secondary: #2a2a2a;
    --text-primary: #e0e0e0;
    --text-secondary: #b0b0b0;
    --border-color: #404040;
    --accent-original: #5a9fe0;
    --accent-translated: #5ab87a;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    font-size: 16px;
    line-height: 1.6;
    color: var(--text-primary);
    background-color: var(--bg-primary);
}
.bilingual-document { max-width: 1400px; margin: 0 auto; padding: 20px; }
.bilingual-page {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
    margin-bottom: 30px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    overflow: hidden;
}
.original-section, .translated-section {
    padding: 30px;
}
.original-section {
    border-right: 2px solid var(--accent-original);
}
.translated-section {
    border-left: 2px solid var(--accent-translated);
}
.section-label {
    font-size: 12px;
    font-weight: 600;
    text-transform: uppercase;
    color: var(--text-secondary);
    margin-bottom: 15px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border-color);
}
.original-content, .translated-content {
    white-space: pre-wrap;
    word-wrap: break-word;
}
@media (max-width: 900px) {
    .bilingual-page {
        grid-template-columns: 1fr;
    }
    .original-section {
        border-right: none;
        border-bottom: 2px solid var(--accent-original);
    }
}
"#
    }
    
    /// 双语对照样式 (段落交错模式)
    fn get_bilingual_interleaved_css() -> &'static str {
        r#"
:root {
    --bg-primary: #1a1a1a;
    --bg-secondary: #2a2a2a;
    --text-primary: #e0e0e0;
    --text-secondary: #b0b0b0;
    --border-color: #404040;
    --accent-original: #5a9fe0;
    --accent-translated: #5ab87a;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    font-size: 16px;
    line-height: 1.6;
    color: var(--text-primary);
    background-color: var(--bg-primary);
}
.bilingual-document-interleaved { max-width: 900px; margin: 0 auto; padding: 20px; }
.bilingual-page {
    margin-bottom: 30px;
}
.paragraph-pair {
    margin-bottom: 25px;
    padding: 20px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 8px;
}
.original-paragraph {
    margin-bottom: 15px;
    padding-bottom: 15px;
    border-bottom: 2px solid var(--accent-original);
}
.translated-paragraph {
    padding-top: 15px;
}
.original-paragraph::before {
    content: "原文";
    display: inline-block;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    color: var(--accent-original);
    margin-bottom: 8px;
}
.translated-paragraph::before {
    content: "译文";
    display: inline-block;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    color: var(--accent-translated);
    margin-bottom: 8px;
}
"#
    }
}

#[derive(Debug, Clone)]
pub struct SearchResult {
    pub page: usize,
    pub position: usize,
    pub context: String,
}

#[derive(Debug, Clone)]
pub struct TocEntry {
    pub title: String,
    pub page: usize,
    pub level: usize,
}