//! Vue CSS Isolation - Generate unique class names to avoid CSS selector conflicts
//! Vue CSS 隔离 - 生成唯一的类名避免 CSS 选择器冲突

use std::collections::HashMap;
use std::hash::{Hash, Hasher};
use std::collections::hash_map::DefaultHasher;

/// Vue CSS 隔离器
pub struct VueCssIsolator;

impl VueCssIsolator {
    /// 为 Vue 组件标签添加唯一的 class_iris 属性
    /// 目的：避免 CSS 选择器选中或漏选，保持原有行为
    pub fn add_unique_class(html: &str, vue_components: &[String]) -> String {
        let mut result = html.to_string();
        let mut class_cache: HashMap<String, String> = HashMap::new();
        
        for component_name in vue_components {
            // 为每个组件生成唯一的 class_iris 值
            let unique_class = if let Some(cached) = class_cache.get(component_name) {
                cached.clone()
            } else {
                let unique_class = Self::generate_unique_class(component_name);
                class_cache.insert(component_name.clone(), unique_class.clone());
                unique_class
            };
            
            // 替换开始标签，添加 class_iris 属性
            let patterns = [
                // <Component attr1="value1" ...>
                (format!("<{} ", component_name), 
                 format!("<{} class_iris=\"{}\" ", component_name, unique_class)),
                // <Component>
                (format!("<{}>", component_name), 
                 format!("<{} class_iris=\"{}\">", component_name, unique_class)),
            ];
            
            for (from, to) in patterns {
                result = result.replace(&from, &to);
            }
        }
        
        result
    }
    
    /// 生成唯一的 class_iris 值
    fn generate_unique_class(component_name: &str) -> String {
        // 使用组件名 + 时间戳生成唯一标识
        let mut hasher = DefaultHasher::new();
        component_name.hash(&mut hasher);
        let hash = hasher.finish();
        
        // 转换为 base62 编码（a-z, A-Z, 0-9）
        format!("iris_{}", Self::to_base62(hash))
    }
    
    /// 将 u64 转换为 base62 字符串
    fn to_base62(mut num: u64) -> String {
        const BASE62: &[u8] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        let mut result = String::new();
        
        if num == 0 {
            return "a".to_string();
        }
        
        while num > 0 {
            result.push(BASE62[(num % 62) as usize] as char);
            num /= 62;
        }
        
        result.chars().rev().collect()
    }
    
    /// 重写 CSS 选择器，为组件选择器添加 class_iris 限定
    /// 例如：`.el-button` → `.el-button[class_iris="xyz123"]`
    pub fn rewrite_css_selectors(css: &str, component_classes: &HashMap<String, String>) -> String {
        let mut result = css.to_string();
        
        for (component_name, unique_class) in component_classes {
            // 查找组件相关的 CSS 选择器
            // 简单实现：为所有包含组件名的选择器添加 class_iris 限定
            let selector_patterns = [
                // .ComponentName
                (format!(".{}", component_name), 
                 format!(".{}[class_iris=\"{}\"]", component_name, unique_class)),
                // .ComponentName.xxx
                (format!(".{}.", component_name), 
                 format!(".{}[class_iris=\"{}\"].", component_name, unique_class)),
            ];
            
            for (from, to) in selector_patterns {
                result = result.replace(&from, &to);
            }
        }
        
        result
    }
}

/// 完整的 Vue SFC CSS 隔离处理
pub fn isolate_vue_css(
    template_html: &str,
    style_content: &str,
    vue_components: &[String],
) -> (String, String) {
    // 1. 为 Vue 组件添加唯一的 class_iris 属性
    let isolated_html = VueCssIsolator::add_unique_class(template_html, vue_components);
    
    // 2. 重写 CSS 选择器
    let component_classes: HashMap<String, String> = vue_components
        .iter()
        .map(|name| {
            let unique_class = VueCssIsolator::generate_unique_class(name);
            (name.clone(), unique_class)
        })
        .collect();
    
    let isolated_css = VueCssIsolator::rewrite_css_selectors(style_content, &component_classes);
    
    (isolated_html, isolated_css)
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_add_unique_class_to_components() {
        let html = r#"<div><ElButton type="primary">Click</ElButton><MyComponent /></div>"#;
        let components = vec!["ElButton".to_string(), "MyComponent".to_string()];
        
        let isolated = VueCssIsolator::add_unique_class(html, &components);
        
        println!("Isolated HTML:\n{}", isolated);
        
        // 组件应该添加 class_iris 属性
        assert!(isolated.contains("ElButton") && isolated.contains("class_iris="));
        assert!(isolated.contains("MyComponent") && isolated.contains("class_iris="));
        
        // 原生 HTML 不加 class_iris（检查 div 标签本身没有 class_iris）
        assert!(isolated.contains("<div>"));
        assert!(!isolated.contains("<div class_iris="));
    }
    
    #[test]
    fn test_generate_unique_class() {
        let class1 = VueCssIsolator::generate_unique_class("ElButton");
        let class2 = VueCssIsolator::generate_unique_class("ElButton");
        let class3 = VueCssIsolator::generate_unique_class("MyComponent");
        
        // 同一组件生成相同的 class
        assert_eq!(class1, class2);
        
        // 不同组件生成不同的 class
        assert_ne!(class1, class3);
        
        // class 格式应该是 iris_xxx
        assert!(class1.starts_with("iris_"));
    }
    
    #[test]
    fn test_rewrite_css_selectors() {
        let css = r#"
        .ElButton {
            color: blue;
        }
        .ElButton.primary {
            background: green;
        }
        "#;
        
        let mut classes = HashMap::new();
        classes.insert("ElButton".to_string(), "iris_abc123".to_string());
        
        let rewritten = VueCssIsolator::rewrite_css_selectors(css, &classes);
        
        println!("Rewritten CSS:\n{}", rewritten);
        
        // CSS 选择器应该被添加 class_iris 限定
        assert!(rewritten.contains(".ElButton[class_iris=\"iris_abc123\"]"));
    }
}
