//! 渲染器模块
//! 
//! 提供统一的文档渲染接口，支持代码、Markdown、PDF 等多种格式

use anyhow::Result;
use crate::core::code_reader::{CodeReader, CodeDocument};

/// 渲染主题
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum RenderTheme {
    Light,
    Dark,
    Solarized,
    Monokai,
}

impl RenderTheme {
    /// 获取主题名称
    pub fn name(&self) -> &'static str {
        match self {
            RenderTheme::Light => "Light",
            RenderTheme::Dark => "Dark",
            RenderTheme::Solarized => "Solarized",
            RenderTheme::Monokai => "Monokai",
        }
    }
    
    /// 从字符串解析主题
    pub fn from_str(s: &str) -> Self {
        match s.to_lowercase().as_str() {
            "light" => RenderTheme::Light,
            "solarized" => RenderTheme::Solarized,
            "monokai" => RenderTheme::Monokai,
            _ => RenderTheme::Dark,
        }
    }
}

/// 渲染配置
#[derive(Debug, Clone)]
pub struct RenderConfig {
    pub theme: RenderTheme,
    pub font_size: u16,
    pub line_height: f32,
    pub show_line_numbers: bool,
    pub word_wrap: bool,
    pub minimap: bool,
}

impl Default for RenderConfig {
    fn default() -> Self {
        Self {
            theme: RenderTheme::Dark,
            font_size: 14,
            line_height: 1.6,
            show_line_numbers: true,
            word_wrap: false,
            minimap: false,
        }
    }
}

/// 文档类型
#[derive(Debug, Clone)]
pub enum DocumentType {
    Code(CodeDocument),
    Markdown(String),
    PDF(Vec<u8>),
    PlainText(String),
}

/// 渲染器
pub struct Renderer {
    config: RenderConfig,
    code_reader: CodeReader,
}

impl Renderer {
    /// 创建渲染器
    pub fn new(config: RenderConfig) -> Result<Self> {
        let code_reader = CodeReader::new()?;
        
        Ok(Self {
            config,
            code_reader,
        })
    }
    
    /// 渲染文档为 HTML
    pub fn render_to_html(&self, doc: &DocumentType) -> Result<String> {
        match doc {
            DocumentType::Code(code_doc) => self.render_code(code_doc),
            DocumentType::Markdown(md_content) => self.render_markdown(md_content),
            DocumentType::PDF(_) => Ok("<p>PDF rendering not yet implemented</p>".to_string()),
            DocumentType::PlainText(text) => self.render_plain_text(text),
        }
    }
    
    /// 渲染代码文档
    fn render_code(&self, doc: &CodeDocument) -> Result<String> {
        let html = self.code_reader.render(doc)?;
        Ok(html)
    }
    
    /// 渲染 Markdown
    fn render_markdown(&self, content: &str) -> Result<String> {
        use pulldown_cmark::{Parser, Options, html};
        
        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(content, options);
        
        let mut html_output = String::new();
        html::push_html(&mut html_output, parser);
        
        // 包装完整的 HTML 文档
        let full_html = format!(
            r#"<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Markdown Document</title>
    <style>{}</style>
</head>
<body>
    <div class="markdown-body">
        {}
    </div>
</body>
</html>"#,
            self.get_markdown_css(),
            html_output
        );
        
        Ok(full_html)
    }
    
    /// 渲染纯文本
    fn render_plain_text(&self, text: &str) -> Result<String> {
        let escaped = text
            .replace('&', "&amp;")
            .replace('<', "&lt;")
            .replace('>', "&gt;");
        
        let html = format!(
            r#"<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Plain Text</title>
    <style>{}</style>
</head>
<body>
    <pre class="plain-text">{}</pre>
</body>
</html>"#,
            self.get_plain_text_css(),
            escaped
        );
        
        Ok(html)
    }
    
    /// 获取 Markdown 样式
    fn get_markdown_css(&self) -> &'static str {
        r#"
:root {
    --bg-primary: #1a1a2e;
    --bg-secondary: #16213e;
    --text-primary: #eaeaea;
    --text-secondary: #a0a0a0;
    --accent-color: #00adb5;
    --border-color: #2a2a4a;
    --code-bg: #0f3460;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
    font-size: 16px;
    line-height: 1.6;
    background-color: var(--bg-primary);
    color: var(--text-primary);
    padding: 20px;
}
.markdown-body {
    max-width: 900px;
    margin: 0 auto;
    background: var(--bg-secondary);
    padding: 40px;
    border-radius: 8px;
    border: 1px solid var(--border-color);
}
.markdown-body h1, .markdown-body h2, .markdown-body h3, 
.markdown-body h4, .markdown-body h5, .markdown-body h6 {
    margin-top: 24px;
    margin-bottom: 16px;
    font-weight: 600;
    line-height: 1.25;
    color: var(--text-primary);
}
.markdown-body h1 { font-size: 2em; border-bottom: 1px solid var(--border-color); padding-bottom: 0.3em; }
.markdown-body h2 { font-size: 1.5em; border-bottom: 1px solid var(--border-color); padding-bottom: 0.3em; }
.markdown-body h3 { font-size: 1.25em; }
.markdown-body p { margin-bottom: 16px; }
.markdown-body a { color: var(--accent-color); text-decoration: none; }
.markdown-body a:hover { text-decoration: underline; }
.markdown-body code {
    background-color: var(--code-bg);
    padding: 0.2em 0.4em;
    border-radius: 3px;
    font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
    font-size: 85%;
}
.markdown-body pre {
    background-color: var(--code-bg);
    padding: 16px;
    border-radius: 6px;
    overflow: auto;
    margin-bottom: 16px;
}
.markdown-body pre code {
    background: none;
    padding: 0;
    font-size: 100%;
}
.markdown-body blockquote {
    border-left: 4px solid var(--accent-color);
    padding: 0 16px;
    color: var(--text-secondary);
    margin-bottom: 16px;
}
.markdown-body ul, .markdown-body ol {
    padding-left: 2em;
    margin-bottom: 16px;
}
.markdown-body li { margin-bottom: 8px; }
.markdown-body table {
    border-collapse: collapse;
    width: 100%;
    margin-bottom: 16px;
}
.markdown-body th, .markdown-body td {
    border: 1px solid var(--border-color);
    padding: 8px 12px;
    text-align: left;
}
.markdown-body th {
    background-color: var(--code-bg);
    font-weight: 600;
}
.markdown-body img {
    max-width: 100%;
    height: auto;
    border-radius: 4px;
}
.markdown-body hr {
    border: none;
    border-top: 1px solid var(--border-color);
    margin: 24px 0;
}
"#
    }
    
    /// 获取纯文本样式
    fn get_plain_text_css(&self) -> &'static str {
        r#"
:root {
    --bg-primary: #1a1a2e;
    --text-primary: #eaeaea;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
    font-family: "SF Mono", Monaco, "Cascadia Code", monospace;
    font-size: 14px;
    line-height: 1.6;
    background-color: var(--bg-primary);
    color: var(--text-primary);
    padding: 20px;
}
.plain-text {
    white-space: pre-wrap;
    word-wrap: break-word;
    max-width: 1200px;
    margin: 0 auto;
}
"#
    }
    
    /// 更新配置
    pub fn update_config(&mut self, config: RenderConfig) {
        self.config = config;
    }
    
    /// 切换主题
    pub fn toggle_theme(&mut self) {
        self.config.theme = match self.config.theme {
            RenderTheme::Dark => RenderTheme::Light,
            _ => RenderTheme::Dark,
        };
    }
    
    /// 调整字体大小
    pub fn adjust_font_size(&mut self, delta: i16) {
        let new_size = self.config.font_size as i16 + delta;
        self.config.font_size = new_size.clamp(10, 24) as u16;
    }
}

// TODO: Dioxus UI 组件集成（后续 Phase 2 完成）
// 当前版本专注于核心渲染逻辑

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_renderer_creation() {
        let renderer = Renderer::new(RenderConfig::default());
        assert!(renderer.is_ok());
    }
    
    #[test]
    fn test_theme_toggle() {
        let mut renderer = Renderer::new(RenderConfig::default()).unwrap();
        assert_eq!(renderer.config.theme, RenderTheme::Dark);
        
        renderer.toggle_theme();
        assert_eq!(renderer.config.theme, RenderTheme::Light);
    }
    
    #[test]
    fn test_font_size_adjust() {
        let mut renderer = Renderer::new(RenderConfig::default()).unwrap();
        let initial_size = renderer.config.font_size;
        
        renderer.adjust_font_size(2);
        assert_eq!(renderer.config.font_size, initial_size + 2);
        
        renderer.adjust_font_size(-5);
        assert!(renderer.config.font_size >= 10);
    }
    
    #[test]
    fn test_markdown_rendering() {
        let renderer = Renderer::new(RenderConfig::default()).unwrap();
        let md = "# Hello\n\nThis is **bold** and this is *italic*.";
        let result = renderer.render_to_html(&DocumentType::Markdown(md.to_string()));
        
        assert!(result.is_ok());
        let html = result.unwrap();
        assert!(html.contains("<h1>Hello</h1>"));
        assert!(html.contains("<strong>bold</strong>"));
        assert!(html.contains("<em>italic</em>"));
    }
}
