//! Form execution logic
//!
//! Handles form execution with various backends and execution modes.

use crate::error::Result;
use crate::prompts;
use std::collections::{BTreeMap, HashMap};
use std::path::Path;

use super::conditions::evaluate_condition;
use super::parser::load_elements_from_file;
use super::translation::{translate_display_item, translate_field_definition};
use super::types::{
    DisplayItem, DisplayMode, FieldDefinition, FieldType, FormDefinition, FormElement,
};

#[cfg(feature = "i18n")]
use crate::i18n::I18nBundle;

#[cfg(not(feature = "i18n"))]
type I18nBundle = ();

/// Render a display item with formatting, respecting conditionals
pub fn render_display_item(item: &DisplayItem, results: &HashMap<String, serde_json::Value>) {
    // Check if item should be shown based on conditional
    if let Some(condition) = &item.when {
        if !evaluate_condition(condition, results) {
            // Item condition not met, skip it
            return;
        }
    }

    if !item.should_display() {
        return;
    }

    let default_margin = item.margin_left.unwrap_or(0);
    let border_margin = item.border_margin_left.unwrap_or(default_margin);
    let content_margin = item.content_margin_left.unwrap_or(default_margin);

    let border_margin_str = " ".repeat(border_margin);
    let content_margin_str = " ".repeat(content_margin);

    // Top border line
    if item.border_top.unwrap_or(false) {
        let top_l = item.border_top_l.as_deref().unwrap_or("");
        let top_char = item.border_top_char.as_deref().unwrap_or("═");
        let top_len = item.border_top_len.unwrap_or(60);
        let top_r = item.border_top_r.as_deref().unwrap_or("");
        let top_border = top_char.repeat(top_len);
        println!("{}{}{}{}", border_margin_str, top_l, top_border, top_r);
    }

    // Title
    if let Some(title) = &item.title {
        if !title.is_empty() {
            println!("{}{}", content_margin_str, title);
        }
    }

    // Content
    if let Some(content) = &item.content {
        if !content.is_empty() {
            for line in content.lines() {
                println!("{}{}", content_margin_str, line);
            }
        }
    }

    // Bottom border line
    if item.border_bottom.unwrap_or(false) {
        let bottom_l = item.border_bottom_l.as_deref().unwrap_or("");
        let bottom_char = item.border_bottom_char.as_deref().unwrap_or("═");
        let bottom_len = item.border_bottom_len.unwrap_or(60);
        let bottom_r = item.border_bottom_r.as_deref().unwrap_or("");
        let bottom_border = bottom_char.repeat(bottom_len);
        println!(
            "{}{}{}{}",
            border_margin_str, bottom_l, bottom_border, bottom_r
        );
    }
}

pub fn execute_with_base_dir(
    mut form: FormDefinition,
    base_dir: &Path,
) -> Result<HashMap<String, serde_json::Value>> {
    let mut results = HashMap::new();

    // Print form header
    if let Some(desc) = &form.description {
        println!("\n{}\n{}\n", form.name, desc);
    } else {
        println!("\n{}\n", form.name);
    }

    // Migrate legacy format to unified elements
    form.migrate_to_elements();

    // Expand groups with includes using the unified expand_includes function
    let expanded_form = super::fragments::expand_includes(form, base_dir)?;

    // Build ordered element map
    let mut element_map: BTreeMap<usize, FormElement> = BTreeMap::new();
    let mut order_counter = 0;

    for element in expanded_form.elements {
        let order = match &element {
            FormElement::Item(item) => {
                if item.order == 0 {
                    order_counter += 1;
                    order_counter - 1
                } else {
                    item.order
                }
            }
            FormElement::Field(field) => {
                if field.order == 0 {
                    order_counter += 1;
                    order_counter - 1
                } else {
                    field.order
                }
            }
        };
        element_map.insert(order, element);
    }

    // Process elements in order
    for (_, element) in element_map.iter() {
        match element {
            FormElement::Item(item) => {
                render_display_item(item, &results);
            }
            FormElement::Field(field) => {
                // Check if field should be shown based on conditional
                if let Some(condition) = &field.when {
                    if !evaluate_condition(condition, &results) {
                        // Field condition not met, skip it
                        continue;
                    }
                }

                let value = execute_field(field, &results)?;
                results.insert(field.name.clone(), value.clone());
            }
        }
    }

    Ok(results)
}

/// Execute a form and collect results (no path resolution - for backwards compatibility)
pub fn execute(form: FormDefinition) -> Result<HashMap<String, serde_json::Value>> {
    execute_with_base_dir(form, Path::new("."))
}

/// Load form from TOML file and execute with proper path resolution
pub fn load_and_execute_from_file(
    path: impl AsRef<Path>,
) -> Result<HashMap<String, serde_json::Value>> {
    use super::parser::{parse_toml, resolve_constraints_in_content};

    let path_ref = path.as_ref();
    let content = std::fs::read_to_string(path_ref)?;

    // Get the directory of the current file for relative path resolution
    let base_dir = path_ref.parent().unwrap_or_else(|| Path::new("."));

    // Resolve constraint interpolations before parsing
    let resolved_content = resolve_constraints_in_content(&content, base_dir)?;
    let form = parse_toml(&resolved_content)?;

    execute_with_base_dir(form, base_dir)
}

/// Filter field options based on options_from reference
fn filter_options_from(
    field: &FieldDefinition,
    previous_results: &HashMap<String, serde_json::Value>,
) -> Vec<super::types::SelectOption> {
    // If no options_from specified, return all options
    let Some(ref source_field) = field.options_from else {
        return field.options.clone();
    };

    // Get the source field's value
    let Some(source_value) = previous_results.get(source_field) else {
        // Source field not found, return all options
        return field.options.clone();
    };

    // Extract selected values from source field (could be array or comma-separated string)
    let selected_values: Vec<String> = match source_value {
        serde_json::Value::Array(arr) => arr
            .iter()
            .filter_map(|v| v.as_str().map(|s| s.to_string()))
            .collect(),
        serde_json::Value::String(s) => s.split(',').map(|item| item.trim().to_string()).collect(),
        _ => return field.options.clone(), // Unsupported type, return all
    };

    // Filter options to only include those in selected_values
    field
        .options
        .iter()
        .filter(|opt| selected_values.contains(&opt.value))
        .cloned()
        .collect()
}

/// Execute a single field
fn execute_field(
    field: &FieldDefinition,
    _previous_results: &HashMap<String, serde_json::Value>,
) -> Result<serde_json::Value> {
    let is_required = field.required.unwrap_or(false);
    let required_marker = if is_required { " *" } else { " (optional)" };

    match field.field_type {
        FieldType::Text => {
            let prompt_with_marker = format!("{}{}", field.prompt, required_marker);
            let result = prompts::text(
                &prompt_with_marker,
                field.default.as_deref(),
                field.placeholder.as_deref(),
            )?;

            if is_required && result.is_empty() {
                eprintln!("⚠ This field is required. Please enter a value.");
                return execute_field(field, _previous_results); // Retry
            }
            Ok(serde_json::json!(result))
        }

        FieldType::Confirm => {
            let prompt_with_marker = format!("{}{}", field.prompt, required_marker);
            let default_bool =
                field
                    .default
                    .as_deref()
                    .and_then(|s| match s.to_lowercase().as_str() {
                        "true" | "yes" => Some(true),
                        "false" | "no" => Some(false),
                        _ => None,
                    });
            let result = prompts::confirm(&prompt_with_marker, default_bool, None)?;
            Ok(serde_json::json!(result))
        }

        FieldType::Password => {
            let prompt_with_marker = format!("{}{}", field.prompt, required_marker);
            let with_toggle = field.placeholder.as_deref() == Some("toggle");
            let result = prompts::password(&prompt_with_marker, with_toggle)?;

            if is_required && result.is_empty() {
                eprintln!("⚠ This field is required. Please enter a value.");
                return execute_field(field, _previous_results); // Retry
            }
            Ok(serde_json::json!(result))
        }

        FieldType::Select => {
            if field.options.is_empty() {
                return Err(crate::ErrorWrapper::form_parse_failed(
                    "Select field requires 'options'",
                ));
            }
            let prompt_with_marker = format!("{}{}", field.prompt, required_marker);

            // Filter options based on options_from if specified
            let filtered_options = filter_options_from(field, _previous_results);

            if filtered_options.is_empty() {
                return Err(crate::ErrorWrapper::form_parse_failed(format!(
                    "No options available for field '{}'. Check options_from reference.",
                    field.name
                )));
            }

            let options = filtered_options
                .iter()
                .map(|opt| opt.as_string())
                .collect::<Vec<_>>();
            let result = prompts::select(
                &prompt_with_marker,
                options,
                field.page_size,
                field.vim_mode.unwrap_or(false),
            )?;
            Ok(serde_json::json!(result))
        }

        FieldType::MultiSelect => {
            if field.options.is_empty() {
                return Err(crate::ErrorWrapper::form_parse_failed(
                    "MultiSelect field requires 'options'",
                ));
            }
            let prompt_with_marker = format!("{}{}", field.prompt, required_marker);
            let options = field
                .options
                .iter()
                .map(|opt| opt.as_string())
                .collect::<Vec<_>>();
            let results = prompts::multi_select(
                &prompt_with_marker,
                options,
                field.page_size,
                field.vim_mode.unwrap_or(false),
            )?;

            if is_required && results.is_empty() {
                eprintln!("⚠ This field is required. Please select at least one option.");
                return execute_field(field, _previous_results); // Retry
            }
            Ok(serde_json::json!(results))
        }

        FieldType::Editor => {
            let prompt_with_marker = format!("{}{}", field.prompt, required_marker);
            let result = prompts::editor(
                &prompt_with_marker,
                field.file_extension.as_deref(),
                field.prefix_text.as_deref(),
            )?;

            if is_required && result.is_empty() {
                eprintln!("⚠ This field is required. Please enter a value.");
                return execute_field(field, _previous_results); // Retry
            }
            Ok(serde_json::json!(result))
        }

        FieldType::Date => {
            let prompt_with_marker = format!("{}{}", field.prompt, required_marker);
            let week_start = field.week_start.as_deref().unwrap_or("Mon");
            let result = prompts::date(
                &prompt_with_marker,
                field.default.as_deref(),
                field.min_date.as_deref(),
                field.max_date.as_deref(),
                week_start,
            )?;
            Ok(serde_json::json!(result))
        }

        FieldType::Custom => {
            let prompt_with_marker = format!("{}{}", field.prompt, required_marker);
            let type_name = field.custom_type.as_ref().ok_or_else(|| {
                crate::ErrorWrapper::form_parse_failed("Custom field requires 'custom_type'")
            })?;
            let result = prompts::custom(&prompt_with_marker, type_name, field.default.as_deref())?;

            if is_required && result.is_empty() {
                eprintln!("⚠ This field is required. Please enter a value.");
                return execute_field(field, _previous_results); // Retry
            }
            Ok(serde_json::json!(result))
        }

        FieldType::RepeatingGroup => {
            // Temporary stub - will be implemented in FASE 4
            Err(crate::ErrorWrapper::form_parse_failed(
                "RepeatingGroup not yet implemented - use CLI backend (FASE 4)",
            ))
        }
    }
}

/// Build element list from form definition with lazy loading of fragments
fn build_element_list(
    form: &FormDefinition,
    base_dir: &Path,
    _results: &HashMap<String, serde_json::Value>,
) -> Result<Vec<(usize, FormElement)>> {
    let mut element_list: Vec<(usize, FormElement)> = Vec::new();
    let mut order_counter = 0;

    // Process unified elements (expand groups and maintain insertion order)
    for element in form.elements.iter() {
        match element {
            FormElement::Item(item) => {
                let mut item_clone = item.as_ref().clone();

                // Handle group type with includes
                if item.item_type == "group" {
                    let group_condition = item.when.clone();
                    if let Some(includes) = &item.includes {
                        for include_path in includes {
                            // Load elements from fragment (unified format)
                            // Note: We load ALL fragments regardless of condition
                            // Phase 3 filtering will hide/show based on conditions
                            match load_elements_from_file(include_path, base_dir) {
                                Ok(loaded_elements) => {
                                    for mut loaded_element in loaded_elements {
                                        // Apply group condition to loaded elements if they don't have one
                                        if let Some(ref condition) = group_condition {
                                            match &mut loaded_element {
                                                FormElement::Item(ref mut loaded_item) => {
                                                    if loaded_item.when.is_none() {
                                                        loaded_item.when = Some(condition.clone());
                                                    }
                                                }
                                                FormElement::Field(ref mut loaded_field) => {
                                                    if loaded_field.when.is_none() {
                                                        loaded_field.when = Some(condition.clone());
                                                    }
                                                }
                                            }
                                        }
                                        // Assign order based on position counter (insertion order)
                                        match &mut loaded_element {
                                            FormElement::Item(ref mut loaded_item) => {
                                                loaded_item.order = order_counter;
                                            }
                                            FormElement::Field(ref mut loaded_field) => {
                                                loaded_field.order = order_counter;
                                            }
                                        }
                                        order_counter += 1;
                                        element_list.push((order_counter - 1, loaded_element));
                                    }
                                }
                                Err(_) => {
                                    // Fragment failed to load, skip silently
                                }
                            }
                        }
                    }
                } else {
                    // Non-group items get order from position counter (insertion order)
                    item_clone.order = order_counter;
                    order_counter += 1;
                    element_list.push((item_clone.order, FormElement::Item(Box::new(item_clone))));
                }
            }
            FormElement::Field(field) => {
                let mut field_clone = field.as_ref().clone();
                // Assign order based on position counter (insertion order)
                field_clone.order = order_counter;
                order_counter += 1;
                element_list.push((field_clone.order, FormElement::Field(Box::new(field_clone))));
            }
        }
    }

    // No need to sort - elements are already in insertion order from the counter
    // element_list is already sorted by construction

    Ok(element_list)
}

/// Recompute visible elements based on current results
///
/// This function rebuilds the element list with lazy loading based on current results,
/// filtering out elements whose conditions don't match. Used for reactive rendering
/// in TUI and Web backends when user input changes selections that affect conditionals.
///
/// # Arguments
///
/// * `form` - The form definition
/// * `base_dir` - Base directory for resolving relative paths
/// * `results` - Current accumulated results (used for condition evaluation)
///
/// # Returns
///
/// A tuple of (filtered items, filtered fields) that should be displayed
/// based on current conditions and lazy loading rules
pub fn recompute_visible_elements(
    form: &FormDefinition,
    base_dir: &Path,
    results: &HashMap<String, serde_json::Value>,
) -> Result<(Vec<DisplayItem>, Vec<FieldDefinition>)> {
    // Clone and migrate form to ensure elements are populated
    let mut form_clone = form.clone();
    form_clone.migrate_to_elements();

    // Build complete element list with lazy loading
    let element_list = build_element_list(&form_clone, base_dir, results)?;

    // Separate and filter items and fields based on conditions
    let mut visible_items = Vec::new();
    let mut visible_fields = Vec::new();

    for (_, element) in element_list {
        match element {
            FormElement::Item(item) => {
                // Include item if it has no condition, or condition is true
                let should_show = item
                    .when
                    .as_ref()
                    .is_none_or(|cond| evaluate_condition(cond, results));

                if should_show {
                    visible_items.push(*item);
                }
            }
            FormElement::Field(field) => {
                // Include field if it has no condition, or condition is true
                let should_show = field
                    .when
                    .as_ref()
                    .is_none_or(|cond| evaluate_condition(cond, results));

                if should_show {
                    visible_fields.push(*field);
                }
            }
        }
    }

    Ok((visible_items, visible_fields))
}

/// Execute a form using two-phase execution (for sequential CLI-like backends)
///
/// This execution strategy is designed for backends that execute fields sequentially
/// and cannot "go back" to modify previous selections. It uses a two-phase approach:
///
/// **Phase 1:** Identify and execute selector fields (fields that control conditionals)
/// **Phase 2:** With selector values known, rebuild element list and execute remaining fields
///
/// This ensures fragments are only loaded after their controlling conditions are determined.
///
/// # Arguments
///
/// * `form` - The parsed form definition
/// * `backend` - A mutable reference to the form backend implementation
/// * `i18n_bundle` - Optional I18n bundle for translating form content
/// * `base_dir` - Base directory for resolving relative paths in includes
///
/// # Returns
///
/// A HashMap containing all field results (name -> value)
/// Unified form execution with all options (primary implementation)
/// Handles: two-phase execution, display modes, i18n, initial values, base_dir resolution
pub async fn execute_with_backend_complete(
    form: FormDefinition,
    backend: &mut dyn crate::backends::FormBackend,
    i18n_bundle: Option<&I18nBundle>,
    base_dir: &Path,
    initial_values: Option<HashMap<String, serde_json::Value>>,
) -> Result<HashMap<String, serde_json::Value>> {
    use crate::backends::RenderContext;

    // Store initial values for later merging before unwrap_or_default
    let initial_backup = initial_values.clone();
    let mut results = initial_values.unwrap_or_default();

    // Initialize backend
    backend.initialize().await?;

    // PHASE 1: Identify selector fields and execute them first
    let selector_field_names = super::conditions::identify_selector_fields(&form);

    for field_name in &selector_field_names {
        if let Some(field) = form.fields.iter().find(|f| &f.name == field_name) {
            let translated_field = translate_field_definition(field, i18n_bundle);
            let context = RenderContext {
                results: results.clone(),
                locale: None,
            };
            let value = backend.execute_field(&translated_field, &context).await?;
            results.insert(field.name.clone(), value);
        }
    }

    // PHASE 2: Build element list with lazy loading based on Phase 1 results
    let element_list = build_element_list(&form, base_dir, &results)?;

    // PHASE 3: Execute remaining fields based on display mode
    if form.display_mode == DisplayMode::Complete {
        // Complete mode: pass all fields to backend for complete form display
        let items: Vec<&DisplayItem> = element_list
            .iter()
            .filter_map(|(_, e)| match e {
                FormElement::Item(item) => Some(item.as_ref()),
                _ => None,
            })
            .collect();

        let fields: Vec<&FieldDefinition> = element_list
            .iter()
            .filter_map(|(_, e)| match e {
                FormElement::Field(field) => {
                    // Skip selector fields (already executed in Phase 1)
                    if selector_field_names.contains(&field.name) {
                        return None;
                    }
                    Some(field.as_ref())
                }
                _ => None,
            })
            .collect();

        let items_owned: Vec<DisplayItem> = items
            .iter()
            .map(|i| translate_display_item(i, i18n_bundle))
            .collect();
        let fields_owned: Vec<FieldDefinition> = fields
            .iter()
            .map(|f| translate_field_definition(f, i18n_bundle))
            .collect();

        results = backend
            .execute_form_complete(&form, base_dir, items_owned, fields_owned, initial_backup)
            .await?;
    } else {
        // Field-by-field mode: iterate through element list
        let mut context = RenderContext {
            results: results.clone(),
            locale: None,
        };

        for (_, element) in element_list.iter() {
            match element {
                FormElement::Item(item) => {
                    if let Some(condition) = &item.when {
                        if !evaluate_condition(condition, &results) {
                            continue;
                        }
                    }
                    context.results = results.clone();
                    let translated_item = translate_display_item(item, i18n_bundle);
                    backend
                        .render_display_item(&translated_item, &context)
                        .await?;
                }
                FormElement::Field(field) => {
                    if selector_field_names.contains(&field.name) {
                        continue;
                    }

                    if let Some(condition) = &field.when {
                        if !evaluate_condition(condition, &results) {
                            continue;
                        }
                    }

                    context.results = results.clone();
                    let translated_field = translate_field_definition(field, i18n_bundle);
                    let value = backend.execute_field(&translated_field, &context).await?;
                    results.insert(field.name.clone(), value);
                }
            }
        }
    }

    // Shutdown backend
    backend.shutdown().await?;

    Ok(results)
}

/// Two-phase execution: selectors first, then dynamic fragments, then remaining fields
pub async fn execute_with_backend_two_phase(
    form: FormDefinition,
    backend: &mut dyn crate::backends::FormBackend,
    i18n_bundle: Option<&I18nBundle>,
    base_dir: &Path,
) -> Result<HashMap<String, serde_json::Value>> {
    execute_with_backend_two_phase_with_defaults(form, backend, i18n_bundle, base_dir, None).await
}

/// Two-phase execution with initial values
pub async fn execute_with_backend_two_phase_with_defaults(
    mut form: FormDefinition,
    backend: &mut dyn crate::backends::FormBackend,
    i18n_bundle: Option<&I18nBundle>,
    base_dir: &Path,
    initial_values: Option<HashMap<String, serde_json::Value>>,
) -> Result<HashMap<String, serde_json::Value>> {
    use crate::backends::RenderContext;

    let initial_backup = initial_values.clone();
    let mut results = initial_values.unwrap_or_default();

    // Migrate legacy format (items/fields) to new unified elements format
    form.migrate_to_elements();

    // Initialize backend
    backend.initialize().await?;

    // PHASE 1: Identify selector fields and execute them first
    let selector_field_names = super::conditions::identify_selector_fields(&form);

    for field_name in &selector_field_names {
        let field_option = form.elements.iter().find_map(|e| {
            if let FormElement::Field(field) = e {
                if &field.name == field_name {
                    Some(field)
                } else {
                    None
                }
            } else {
                None
            }
        });

        if let Some(field) = field_option {
            let translated_field = translate_field_definition(field, i18n_bundle);
            let context = RenderContext {
                results: results.clone(),
                locale: None,
            };
            let value = backend.execute_field(&translated_field, &context).await?;
            results.insert(field.name.clone(), value);
        }
    }

    // PHASE 2: Build element list with lazy loading based on Phase 1 results
    let mut element_list = build_element_list(&form, base_dir, &results)?;

    // Apply initial_values to field.default for all expanded elements
    // This ensures defaults from nickel-roundtrip input files are shown in the UI
    if let Some(ref init_vals) = initial_backup {
        for (_, element) in element_list.iter_mut() {
            if let FormElement::Field(field) = element {
                if let Some(value) = init_vals.get(&field.name) {
                    if field.default.is_none() {
                        field.default = Some(super::conditions::value_to_string(value));
                    }
                }
            }
        }
    }

    // PHASE 3: Execute remaining fields (non-selectors)
    let mut context = RenderContext {
        results: results.clone(),
        locale: None,
    };

    for (_, element) in element_list.iter() {
        match element {
            FormElement::Item(item) => {
                if let Some(condition) = &item.when {
                    if !evaluate_condition(condition, &results) {
                        continue;
                    }
                }
                context.results = results.clone();
                let translated_item = translate_display_item(item, i18n_bundle);
                backend
                    .render_display_item(&translated_item, &context)
                    .await?;
            }
            FormElement::Field(field) => {
                if selector_field_names.contains(&field.name) {
                    continue;
                }

                if let Some(condition) = &field.when {
                    if !evaluate_condition(condition, &results) {
                        continue;
                    }
                }

                context.results = results.clone();
                let translated_field = translate_field_definition(field, i18n_bundle);
                let value = backend.execute_field(&translated_field, &context).await?;
                results.insert(field.name.clone(), value);
            }
        }
    }

    // Merge back initial values for fields not provided by user
    if let Some(init_vals) = &initial_backup {
        for (k, v) in init_vals.iter() {
            if !results.contains_key(k) {
                results.insert(k.clone(), v.clone());
            }
        }
    }

    // Shutdown backend
    backend.shutdown().await?;

    Ok(results)
}

/// Execute a form using a specific backend
///
/// This is the primary async form execution function that integrates
/// with the FormBackend trait abstraction, enabling support for multiple
/// rendering backends (CLI, TUI, Web).
///
/// # Arguments
///
/// * `form` - The parsed form definition
/// * `backend` - A mutable reference to the form backend implementation
/// * `i18n_bundle` - Optional I18n bundle for translating form content
/// * `base_dir` - Base directory for resolving relative paths in includes
///
/// # Returns
///
/// A HashMap containing all field results (name -> value)
/// Execute form with i18n support (sin dos fases - este era el que funcionaba)
pub async fn execute_with_backend_i18n(
    form: FormDefinition,
    backend: &mut dyn crate::backends::FormBackend,
    i18n_bundle: Option<&I18nBundle>,
    base_dir: &Path,
) -> Result<HashMap<String, serde_json::Value>> {
    execute_with_backend_i18n_with_defaults(form, backend, i18n_bundle, base_dir, None).await
}

/// Execute form with i18n support and optional initial values
pub async fn execute_with_backend_i18n_with_defaults(
    form: FormDefinition,
    backend: &mut dyn crate::backends::FormBackend,
    i18n_bundle: Option<&I18nBundle>,
    base_dir: &Path,
    initial_values: Option<HashMap<String, serde_json::Value>>,
) -> Result<HashMap<String, serde_json::Value>> {
    use crate::backends::RenderContext;

    // Store initial values for later merging before unwrap_or_default
    let initial_backup = initial_values.clone();
    let mut results = initial_values.unwrap_or_default();

    // Initialize backend
    backend.initialize().await?;

    // Build element list directly (no two-phase)
    let element_list = build_element_list(&form, base_dir, &results)?;

    // Check display mode and execute accordingly
    if form.display_mode == DisplayMode::Complete {
        // Complete mode: show all fields at once
        // Filter items by 'when' condition
        let items: Vec<&DisplayItem> = element_list
            .iter()
            .filter_map(|(_, e)| match e {
                FormElement::Item(item) => {
                    // Evaluate 'when' condition if present
                    if let Some(condition) = &item.when {
                        if !evaluate_condition(condition, &results) {
                            return None;
                        }
                    }
                    Some(item.as_ref())
                }
                _ => None,
            })
            .collect();

        // Filter fields by 'when' condition
        let fields: Vec<&FieldDefinition> = element_list
            .iter()
            .filter_map(|(_, e)| match e {
                FormElement::Field(field) => {
                    // Evaluate 'when' condition if present
                    if let Some(condition) = &field.when {
                        if !evaluate_condition(condition, &results) {
                            return None;
                        }
                    }
                    Some(field.as_ref())
                }
                _ => None,
            })
            .collect();

        let items_owned: Vec<DisplayItem> = items
            .iter()
            .map(|i| translate_display_item(i, i18n_bundle))
            .collect();
        let fields_owned: Vec<FieldDefinition> = fields
            .iter()
            .map(|f| translate_field_definition(f, i18n_bundle))
            .collect();

        results = backend
            .execute_form_complete(&form, base_dir, items_owned, fields_owned, initial_backup)
            .await?;
    } else {
        // Field-by-field mode
        let mut context = RenderContext {
            results: results.clone(),
            locale: None,
        };

        for (_, element) in element_list.iter() {
            match element {
                FormElement::Item(item) => {
                    context.results = results.clone();
                    let translated_item = translate_display_item(item, i18n_bundle);
                    backend
                        .render_display_item(&translated_item, &context)
                        .await?;
                }
                FormElement::Field(field) => {
                    if let Some(condition) = &field.when {
                        if !evaluate_condition(condition, &results) {
                            continue;
                        }
                    }

                    context.results = results.clone();
                    let translated_field = translate_field_definition(field, i18n_bundle);
                    let value = backend.execute_field(&translated_field, &context).await?;
                    results.insert(field.name.clone(), value);
                }
            }
        }
    }

    // Shutdown backend
    backend.shutdown().await?;

    Ok(results)
}

/// Execute a form using a specific backend (backward compatible wrapper)
///
/// This is a convenience wrapper around `execute_with_backend_i18n` that
/// doesn't use i18n translation. For i18n support, use `execute_with_backend_i18n`.
///
/// # Arguments
///
/// * `form` - The parsed form definition
/// * `backend` - A mutable reference to the form backend implementation
///
/// # Returns
///
/// A HashMap containing all field results (name -> value)
pub async fn execute_with_backend(
    form: FormDefinition,
    backend: &mut dyn crate::backends::FormBackend,
) -> Result<HashMap<String, serde_json::Value>> {
    execute_with_backend_i18n(form, backend, None, Path::new(".")).await
}

pub async fn execute_with_backend_from_dir(
    form: FormDefinition,
    backend: &mut dyn crate::backends::FormBackend,
    base_dir: &Path,
) -> Result<HashMap<String, serde_json::Value>> {
    execute_with_backend_i18n(form, backend, None, base_dir).await
}
