//! Vue Dynamic Features - Inject Vue Runtime for dynamic behavior
//! Vue 动态特性 - 注入 Vue Runtime 实现动态行为

/// Vue 动态特性注入器
pub struct VueDynamicInjector;

impl VueDynamicInjector {
    /// 注入 Vue 动态特性到 script 中
    pub fn inject_dynamic_features(script_content: &str) -> String {
        let mut enhanced_script = String::new();
        
        // 1. 添加 Iris Vue Runtime
        enhanced_script.push_str(Self::iris_vue_runtime());
        enhanced_script.push_str("\n\n");
        
        // 2. 添加用户原始 script
        enhanced_script.push_str(script_content);
        enhanced_script.push_str("\n\n");
        
        // 3. 添加初始化代码
        enhanced_script.push_str(Self::initialization_code());
        
        enhanced_script
    }
    
    /// 为无法解析的组件添加异常标记属性
    /// 正常处理的元素（原生 HTML、已展开的组件）不加任何标记
    pub fn mark_unresolved_components(html: &str, unresolved_components: &[(String, String)]) -> String {
        // unresolved_components: [(组件名, 异常消息), ...]
        let mut result = html.to_string();
        
        for (component_name, error_message) in unresolved_components {
            // 替换开始标签，添加异常属性
            let patterns = [
                (format!("<{} ", component_name), 
                 format!("<{} _iris_sfc_failed=\"{}\" ", component_name, error_message)),
                (format!("<{}>", component_name), 
                 format!("<{} _iris_sfc_failed=\"{}\">", component_name, error_message)),
            ];
            
            for (from, to) in patterns {
                result = result.replace(&from, &to);
            }
        }
        
        result
    }
    
    /// Iris Vue Runtime - 实现 Vue 的 7 大类动态特性
    fn iris_vue_runtime() -> &'static str {
        r#"
// ============================================
// Iris Vue Runtime - Dynamic Feature Handler
// ============================================

/**
 * 一、模板层面动态
 */
function createReactiveSystem() {
  // 1. 动态插值 - {{ }} 运行时解析
  function processInterpolations(element) {
    const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
    let node;
    while (node = walker.nextNode()) {
      const match = node.textContent.match(/\{\{(.+?)\}\}/g);
      if (match) {
        const originalText = node.textContent;
        match.forEach(expr => {
          const code = expr.slice(2, -2).trim();
          try {
            const value = eval(code);
            node.textContent = originalText.replace(expr, value);
          } catch (e) {
            console.warn(`插值解析失败: ${expr}`, e);
          }
        });
      }
    }
  }
  
  // 2. 动态属性绑定 - :prop="value"
  function processDynamicProps(element) {
    const elements = element.querySelectorAll('*');
    elements.forEach(el => {
      Array.from(el.attributes).forEach(attr => {
        if (attr.name.startsWith(':') && !attr.name.startsWith(':is')) {
          const propName = attr.name.slice(1);
          const value = attr.value;
          try {
            const evaluatedValue = eval(value);
            el.removeAttribute(attr.name);
            el.setAttribute(propName, evaluatedValue);
          } catch (e) {
            console.warn(`属性绑定失败: ${attr.name}=${value}`, e);
          }
        }
      });
    });
  }
  
  // 3. 动态事件 - @event="handler"
  function processEventBindings(element) {
    const elements = element.querySelectorAll('*');
    elements.forEach(el => {
      Array.from(el.attributes).forEach(attr => {
        if (attr.name.startsWith('@')) {
          const eventName = attr.name.slice(1);
          const handlerName = attr.value;
          el.removeAttribute(attr.name);
          el.addEventListener(eventName, function(e) {
            if (typeof window[handlerName] === 'function') {
              window[handlerName](e);
            }
          });
        }
      });
    });
  }
  
  // 4. ref 响应式
  function ref(value) {
    const wrapper = { value };
    Object.defineProperty(wrapper, 'value', {
      get() { return value; },
      set(newValue) { 
        value = newValue; 
        triggerUpdates(); 
      }
    });
    return wrapper;
  }
  
  // reactive 响应式对象
  function reactive(obj) {
    return new Proxy(obj, {
      set(target, key, value) {
        target[key] = value;
        triggerUpdates();
        return true;
      }
    });
  }
  
  // computed 计算属性
  function computed(fn) {
    return { get value() { return fn(); } };
  }
  
  // 触发更新
  function triggerUpdates() {
    if (typeof window !== 'undefined' && window._iris_update) {
      window._iris_update();
    }
  }
  
  return { 
    ref, 
    reactive, 
    computed,
    processInterpolations,
    processDynamicProps,
    processEventBindings
  };
}

/**
 * 二、结构渲染动态
 */
function createStructuralDirectives() {
  // v-if 条件渲染
  function processVIf(element) {
    const elements = element.querySelectorAll('[v-if]');
    elements.forEach(el => {
      const condition = el.getAttribute('v-if');
      el.removeAttribute('v-if');
      try {
        const result = eval(condition);
        if (!result) {
          el.style.display = 'none';
          el.setAttribute('data-v-if-hidden', 'true');
        }
      } catch (e) {
        console.warn(`v-if 解析失败: ${condition}`, e);
      }
    });
  }
  
  // v-show 显隐控制
  function processVShow(element) {
    const elements = element.querySelectorAll('[v-show]');
    elements.forEach(el => {
      const condition = el.getAttribute('v-show');
      el.removeAttribute('v-show');
      try {
        const result = eval(condition);
        el.style.display = result ? '' : 'none';
      } catch (e) {
        console.warn(`v-show 解析失败: ${condition}`, e);
      }
    });
  }
  
// v-for 列表渲染
  function processVFor(element) {
    const elements = element.querySelectorAll('[v-for]');
    elements.forEach(el => {
      const expression = el.getAttribute('v-for');
      el.removeAttribute('v-for');
      try {
        // 解析 "item in list" 或 "(item, index) in list" 或 "item of list"
        const match = expression.match(/^\s*(?:\(?\s*(\w+)\s*(?:,\s*(\w+))?\s*\)?)\s+(?:in|of)\s+(.+)\s*$/);
        if (!match) { console.warn('[Iris] v-for 语法无法解析:', expression); return; }

        const itemName = match[1];
        const indexName = match[2] || null;
        const listExpr = match[3].trim();

        // 获取列表数据
        let list;
        try { list = eval(listExpr); } catch(e) { list = []; }
        if (!Array.isArray(list)) list = [];

        const parent = el.parentNode;
        if (!parent) return;

        // 为每一项克隆模板
        list.forEach((item, index) => {
          const clone = el.cloneNode(true);
          // 移除子元素上的 v-for 属性（克隆时已移除）
          // 设置作用域变量
          clone.setAttribute('_vfor_item', JSON.stringify(item));
          clone.setAttribute('_vfor_index', index.toString());
          // 替换插值
          let html = clone.innerHTML;
          const scope = { [itemName]: item };
          if (indexName) scope[indexName] = index;
          html = html.replace(/\{\{\s*(\w+(?:\.\w+)*)\s*\}\}/g, (_, expr) => {
            try { return new Function(...Object.keys(scope), `return ${expr}`)(...Object.values(scope)); }
            catch(e) { return ''; }
          });
          clone.innerHTML = html;
          parent.insertBefore(clone, el);
        });

        // 移除模板元素
        el.remove();
        console.log('[Iris] v-for 已渲染:', expression, `(${list.length} 项)`);
      } catch(e) {
        console.warn('[Iris] v-for 执行失败:', expression, e);
      }
    });
  }
  
  return { processVIf, processVShow, processVFor };
}

/**
 * 三、组件层面动态
 */
function createComponentSystem() {
  const componentRegistry = new Map();
  
  // 注册组件
  function registerComponent(name, component) {
    componentRegistry.set(name, component);
  }
  
  // 解析组件
  function resolveComponent(name) {
    return componentRegistry.get(name);
  }
  
// <component :is="..."> 动态组件
  function processDynamicComponent(element) {
    const dynamicElements = element.querySelectorAll('component[_iris]');
    dynamicElements.forEach(el => {
      const isAttr = el.getAttribute(':is');
      if (isAttr) {
        try {
          const componentName = eval(isAttr);
          const component = resolveComponent(componentName);
          if (component) {
            // 渲染动态组件：替换为组件占位 DOM
            const placeholder = document.createElement('div');
            placeholder.className = `dynamic-component-${componentName}`;
            placeholder.setAttribute('_componentName', componentName);
            placeholder.setAttribute('_iris_sfc_dynamic', 'true');
            if (component.template) {
              placeholder.innerHTML = component.template;
            } else if (typeof component === 'string') {
              placeholder.innerHTML = component;
            }
            el.parentNode.replaceChild(placeholder, el);
            console.log('[Iris] 动态组件已渲染:', componentName);
          } else {
            console.warn('[Iris] 动态组件未注册:', componentName);
          }
        } catch(e) {
          console.warn('[Iris] 动态组件处理失败:', e);
        }
      }
    });
  }
          }
        } catch (e) {
          console.warn(`动态组件解析失败: ${isAttr}`, e);
        }
      }
    });
  }
  
  return { registerComponent, resolveComponent, processDynamicComponent };
}

/**
 * 四、样式动态
 */
function createStyleSystem() {
  // 动态 class
  function processDynamicClass(element) {
    const elements = element.querySelectorAll('[\\:class]');
    elements.forEach(el => {
      const classExpr = el.getAttribute(':class');
      el.removeAttribute(':class');
      try {
        const classValue = eval(classExpr);
        if (typeof classValue === 'object') {
          Object.keys(classValue).forEach(cls => {
            if (classValue[cls]) {
              el.classList.add(cls);
            }
          });
        } else if (typeof classValue === 'string') {
          el.className = classValue;
        }
      } catch (e) {
        console.warn(`动态 class 解析失败: ${classExpr}`, e);
      }
    });
  }
  
  // 动态 style
  function processDynamicStyle(element) {
    const elements = element.querySelectorAll('[\\:style]');
    elements.forEach(el => {
      const styleExpr = el.getAttribute(':style');
      el.removeAttribute(':style');
      try {
        const styleValue = eval(styleExpr);
        if (typeof styleValue === 'object') {
          Object.assign(el.style, styleValue);
        }
      } catch (e) {
        console.warn(`动态 style 解析失败: ${styleExpr}`, e);
      }
    });
  }
  
  return { processDynamicClass, processDynamicStyle };
}

/**
 * 挂载组件
 */
function mountComponent(rootElement) {
  const reactive = createReactiveSystem();
  const structural = createStructuralDirectives();
  const component = createComponentSystem();
  const style = createStyleSystem();
  
  // 处理所有动态特性
  reactive.processInterpolations(rootElement);
  reactive.processDynamicProps(rootElement);
  reactive.processEventBindings(rootElement);
  structural.processVIf(rootElement);
  structural.processVShow(rootElement);
  structural.processVFor(rootElement);
  component.processDynamicComponent(rootElement);
  style.processDynamicClass(rootElement);
  style.processDynamicStyle(rootElement);
  
  return { reactive, structural, component, style };
}

// 导出到全局
window._iris_vue_runtime = {
  mountComponent,
  createReactiveSystem,
  createStructuralDirectives,
  createComponentSystem,
  createStyleSystem
};
"#
    }
    
    /// 初始化代码
    fn initialization_code() -> &'static str {
        r#"
// ============================================
// Iris Initialization
// ============================================

(function() {
  'use strict';
  
  // 等待 DOM 加载完成
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init);
  } else {
    init();
  }
  
  function init() {
    if (typeof window._iris_vue_runtime !== 'undefined') {
      const root = document.querySelector('[data-iris-root]') || document.body;
      window._iris_vue_runtime.mountComponent(root);
      
      window._iris_component = {
        initialized: true,
        mountedAt: Date.now()
      };
      
      console.log('[Iris] Vue Runtime initialized');
    }
  }
})();
"#
    }
}

/// 完整的 Vue SFC 增强处理
pub fn enhance_vue_sfc(
    template_html: &str,
    script_content: &str,
    unresolved_components: &[(String, String)],  // [(组件名, 异常消息), ...]
) -> (String, String) {
    // 1. 为无法解析的组件添加异常标记属性
    let enhanced_html = VueDynamicInjector::mark_unresolved_components(template_html, unresolved_components);
    
    // 2. 注入 Vue Runtime 到 script
    let enhanced_script = VueDynamicInjector::inject_dynamic_features(script_content);
    
    (enhanced_html, enhanced_script)
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_inject_dynamic_features() {
        let script = "const count = ref(0);";
        let enhanced = VueDynamicInjector::inject_dynamic_features(script);
        
        // 包含 7 大类动态特性
        assert!(enhanced.contains("processInterpolations"));      // 动态插值
        assert!(enhanced.contains("processDynamicProps"));        // 动态属性
        assert!(enhanced.contains("processEventBindings"));       // 动态事件
        assert!(enhanced.contains("processVIf"));                 // 条件渲染
        assert!(enhanced.contains("processVFor"));                // 列表渲染
        assert!(enhanced.contains("processDynamicComponent"));    // 动态组件
        assert!(enhanced.contains("processDynamicClass"));        // 动态样式
        
        // 包含用户代码
        assert!(enhanced.contains("const count = ref(0);"));
        
        // 包含初始化代码
        assert!(enhanced.contains("_iris_component"));
    }
    
    #[test]
    fn test_mark_unresolved_components() {
        let html = r#"<div><h1>Title</h1><ResolvedComponent /><UnresolvedWidget /></div>"#;
        
        // 只有无法解析的组件才加异常标记
        let unresolved = vec![
            ("UnresolvedWidget".to_string(), "Component source not found".to_string())
        ];
        let enhanced = VueDynamicInjector::mark_unresolved_components(html, &unresolved);
        
        println!("Enhanced HTML:\n{}", enhanced);
        
        // 已解析的组件不加标记
        assert!(enhanced.contains("<ResolvedComponent />"));
        assert!(!enhanced.contains("ResolvedComponent _iris_sfc_failed"));
        
        // 未解析的组件加异常属性
        assert!(enhanced.contains("UnresolvedWidget _iris_sfc_failed=\"Component source not found\""));
        
        // 原生 HTML 不加标记
        assert!(enhanced.contains("<div>"));
        assert!(enhanced.contains("<h1>"));
    }
}
