//! Vue 项目加载器
//!
//! 从 index.html 开始，加载完整的 Vue 项目，包括：
//! 1. 解析 index.html，构建初始 DOM 树
//! 2. 识别 Vue 挂载点
//! 3. 编译并插入 Vue 组件
//! 4. 返回完整的 DOM 树

use std::path::{Path, PathBuf};
use iris_layout::{
    html::parse_html,
    dom::{DOMNode, DOMTree},
};
use anyhow::Result;
use colored::Colorize;

/// 递归查找指定 ID 的节点
fn find_node_by_id<'a>(node: &'a DOMNode, id: &str) -> Option<&'a DOMNode> {
    if let Some(node_id) = node.get_attribute("id") {
        if node_id == id {
            return Some(node);
        }
    }
    
    for child in &node.children {
        if let Some(found) = find_node_by_id(child, id) {
            return Some(found);
        }
    }
    
    None
}

/// 打印 DOM 树结构（调试用）
fn print_dom_tree(node: &DOMNode, depth: usize) {
    let indent = "  ".repeat(depth);
    
    if node.is_element() {
        let tag = node.tag_name().unwrap_or("unknown");
        let mut desc = format!("{}<{}", indent, tag);
        
        // 添加 id
        if let Some(id) = node.get_attribute("id") {
            desc.push_str(&format!(" id=\"{}\"", id));
        }
        
        // 添加 class
        if let Some(class) = node.get_attribute("class") {
            desc.push_str(&format!(" class=\"{}\"", class));
        }
        
        desc.push('>');
        println!("{}", desc);
        
        // 递归打印子节点
        for child in &node.children {
            print_dom_tree(child, depth + 1);
        }
    } else if node.is_text() {
        let text = node.collect_text();
        let trimmed = text.trim();
        if !trimmed.is_empty() {
            // 安全截断字符串（避免中文字符边界问题）
            let display_text = if trimmed.chars().count() > 50 {
                trimmed.chars().take(50).collect::<String>() + "..."
            } else {
                trimmed.to_string()
            };
            println!("\"{}\"", display_text);
        }
    }
}

/// Vue 项目加载器
pub struct VueProjectLoader {
    project_root: PathBuf,
}

impl VueProjectLoader {
    /// 创建新的项目加载器
    pub fn new(project_root: &Path) -> Self {
        Self {
            project_root: project_root.to_path_buf(),
        }
    }

    /// 加载完整的 Vue 项目
    ///
    /// # 流程
    /// 1. 查找并解析 index.html
    /// 2. 构建初始 DOM 树
    /// 3. 找到 Vue 挂载点
    /// 4. （后续）编译并插入 Vue 组件
    pub fn load_project(&self) -> Result<DOMTree> {
        // 1. 查找 index.html
        let index_html = self.find_index_html()?;
        
        // 2. 解析 HTML
        let html_content = std::fs::read_to_string(&index_html)?;
        
        // 3. 检查 index.html 内容并给出 Vue 模式提示
        self.validate_vue_index_html(&html_content)?;
        
        let dom_tree = parse_html(&html_content);
        
        println!("✓ Parsed index.html from: {}", index_html.display());
        
        // 打印 DOM 树结构
        print_dom_tree(&dom_tree.root(), 0);
        
        // 4. 查找 Vue 挂载点
        if let Some(mount_point) = self.find_vue_mount_point(&dom_tree) {
            println!("✓ Found Vue mount point: #{}", mount_point);
            // TODO: 编译并插入 Vue 组件
        } else {
            println!("ℹ No Vue mount point found, using HTML as-is");
        }
        
        Ok(dom_tree)
    }

    /// 验证 Vue 模式下的 index.html 是否符合规范
    ///
    /// Vue 模式下，index.html 应该是一个空壳，只包含：<div id="app"></div>
    /// 如果包含其他内容（布局、样式等），会输出友好的警告信息
    fn validate_vue_index_html(&self, html_content: &str) -> Result<()> {

        
        // 检查是否有非空内容（除了基本的 HTML 结构和 Vue 挂载点）
        let has_header = html_content.contains("<header");
        let has_footer = html_content.contains("<footer");
        let has_nav = html_content.contains("<nav") || html_content.contains("<aside");
        let has_inline_style = html_content.contains("<style") && html_content.contains("</style>");
        let has_custom_content = html_content.contains("<h1") || html_content.contains("<h2");
        
        // 如果包含任何布局或样式元素，输出警告
        if has_header || has_footer || has_nav || has_inline_style || has_custom_content {
            println!();
            println!("{}", "⚠️  Vue Mode Notice".bright_yellow().bold());
            println!("{}", "─".repeat(60).bright_black());
            println!();
            println!("{}", "In Vue SFC mode, the index.html should be a minimal shell.".yellow());
            println!("{}", "Only an empty mount point is supported:".yellow());
            println!();
            println!("  {}", "<div id=\"app\"></div>".bright_cyan());
            println!();
            println!("{}", "Any additional content (headers, footers, styles, layouts)".bright_black());
            println!("{}", "will be ignored, as Vue components handle all rendering.".bright_black());
            println!();
            println!("{}", "💡 Recommendation:".bright_green());
            println!("{}", "  Move layouts and styles into Vue components (.vue files).".green());
            println!("{}", "  Keep index.html clean and minimal.".green());
            println!();
            println!("{}", "─".repeat(60).bright_black());
            println!();
        }
        
        Ok(())
    }

    /// 查找 index.html 文件
    fn find_index_html(&self) -> Result<PathBuf> {
        // 尝试多个常见位置
        let candidates = vec![
            self.project_root.join("index.html"),
            self.project_root.join("public").join("index.html"),
            self.project_root.join("src").join("index.html"),
        ];

        for candidate in &candidates {
            if candidate.exists() {
                return Ok(candidate.clone());
            }
        }

        // 递归查找
        for entry in walkdir::WalkDir::new(&self.project_root)
            .into_iter()
            .filter_map(|e| e.ok())
            .filter(|e| e.file_type().is_file())
        {
            if let Some(name) = entry.file_name().to_str() {
                if name == "index.html" {
                    return Ok(entry.path().to_path_buf());
                }
            }
        }

        anyhow::bail!("index.html not found in project")
    }

    /// 查找 Vue 挂载点（如 id="app"）
    fn find_vue_mount_point(&self, dom_tree: &DOMTree) -> Option<String> {
        // 常见挂载点 ID
        let common_mount_ids = vec!["app", "root", "vue-app"];
        
        for id in &common_mount_ids {
            // 递归查找子节点
            if find_node_by_id(&dom_tree.root(), id).is_some() {
                println!("  Found mount point: #{}", id);
                return Some(id.to_string());
            }
        }
        
        None
    }

    /// 从 main.ts/main.js 中提取 Vue 挂载点选择器
    ///
    /// 解析类似这样的代码：
    /// ```javascript
    /// createApp(App).mount('#app')
    /// ```
    pub fn extract_mount_selector_from_main(&self) -> Result<Option<String>> {
        // 查找 main.ts 或 main.js
        let main_file = self.find_main_file()?;
        
        if main_file.is_none() {
            return Ok(None);
        }
        
        let main_file = main_file.unwrap();
        let content = std::fs::read_to_string(&main_file)?;
        
        // 使用正则表达式查找 .mount('...') 或 .mount("...")
        let re = regex::Regex::new(r#"\.mount\(\s*['"]([^'"]+)['"]\s*\)"#)?;
        
        if let Some(caps) = re.captures(&content) {
            if let Some(selector) = caps.get(1) {
                return Ok(Some(selector.as_str().to_string()));
            }
        }
        
        Ok(None)
    }

    /// 查找 main.ts 或 main.js 文件
    fn find_main_file(&self) -> Result<Option<PathBuf>> {
        let candidates = vec![
            self.project_root.join("src").join("main.ts"),
            self.project_root.join("src").join("main.js"),
            self.project_root.join("main.ts"),
            self.project_root.join("main.js"),
        ];

        for candidate in &candidates {
            if candidate.exists() {
                return Ok(Some(candidate.clone()));
            }
        }

        Ok(None)
    }

    /// 从 index.html 中提取外部 CSS 文件
    pub fn extract_external_css(&self, dom_tree: &DOMTree) -> Vec<PathBuf> {
        let mut css_files = Vec::new();
        
        fn collect_css(node: &DOMNode, css_files: &mut Vec<PathBuf>, project_root: &Path) {
            // 查找 <link rel="stylesheet" href="...">
            if node.tag_name() == Some("link") {
                if let Some(rel) = node.get_attribute("rel") {
                    if rel == "stylesheet" {
                        if let Some(href) = node.get_attribute("href") {
                            // 解析相对路径
                            let css_path = project_root.join(&href);
                            if css_path.exists() {
                                css_files.push(css_path);
                            }
                        }
                    }
                }
            }
            
            // 递归子节点
            for child in &node.children {
                collect_css(child, css_files, project_root);
            }
        }
        
        collect_css(&dom_tree.root(), &mut css_files, &self.project_root);
        css_files
    }

    /// 从 index.html 中提取内联 <style> 内容
    pub fn extract_inline_styles(&self, dom_tree: &DOMTree) -> Vec<String> {
        let mut styles = Vec::new();
        
        fn collect_styles(node: &DOMNode, styles: &mut Vec<String>) {
            if node.tag_name() == Some("style") {
                let text = node.collect_text();
                if !text.trim().is_empty() {
                    styles.push(text);
                }
            }
            
            for child in &node.children {
                collect_styles(child, styles);
            }
        }
        
        collect_styles(&dom_tree.root(), &mut styles);
        styles
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::fs;
    use tempfile::TempDir;

    #[test]
    fn test_find_index_html() {
        let temp_dir = TempDir::new().unwrap();
        let project_root = temp_dir.path();
        
        // 创建 index.html
        fs::write(project_root.join("index.html"), "<html></html>").unwrap();
        
        let loader = VueProjectLoader::new(project_root);
        let index_html = loader.find_index_html().unwrap();
        
        assert!(index_html.ends_with("index.html"));
    }

    #[test]
    fn test_extract_mount_selector() {
        let temp_dir = TempDir::new().unwrap();
        let project_root = temp_dir.path();
        
        // 创建 src/main.ts
        fs::create_dir_all(project_root.join("src")).unwrap();
        fs::write(
            project_root.join("src").join("main.ts"),
            r#"import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
"#,
        ).unwrap();
        
        let loader = VueProjectLoader::new(project_root);
        let selector = loader.extract_mount_selector_from_main().unwrap();
        
        assert_eq!(selector, Some("#app".to_string()));
    }
}
