//! TUI Backend using ratatui for terminal UI forms
//!
//! Complete ratatui-based terminal UI implementation with full support
//! for all 8 field types, custom widgets, and graceful terminal cleanup.
//!
//! Architecture: State separation (R-STATE-SEPARATION) with event loops
//! for each field type. Terminal lifecycle managed with RAII pattern.

use async_trait::async_trait;
use serde_json::{json, Value};
use std::collections::HashMap;
use std::io;
use std::sync::{Arc, RwLock};
use std::time::Duration;

use super::{FormBackend, RenderContext};
use crate::error::{ErrorWrapper, Result};
use crate::form_parser::{DisplayItem, FieldDefinition, FieldType};

use crossterm::{
    event::{self, Event, KeyCode, KeyModifiers},
    execute,
    terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
};
use ratatui::{
    backend::CrosstermBackend,
    style::{Color, Modifier, Style},
    widgets::{Block, Borders, Paragraph},
    Terminal,
};

/// RAII Guard for terminal cleanup (R-GRACEFUL-SHUTDOWN pattern)
struct TerminalGuard;

impl Drop for TerminalGuard {
    fn drop(&mut self) {
        drop(disable_raw_mode());
        drop(execute!(
            io::stdout(),
            LeaveAlternateScreen,
            event::DisableMouseCapture
        ));
    }
}

/// Panel focus in form view
#[derive(Debug, Clone, Copy, PartialEq)]
enum FormPanel {
    FieldList,
    InputField,
    Buttons,
}

#[derive(Debug, Clone, Copy, PartialEq)]
enum ButtonFocus {
    Cancel,
    Submit,
}

/// Helper to update form elements after a field is saved (reactive re-rendering)
///
/// When a field value changes, conditional sections may appear/disappear.
/// This function recomputes the visible items and fields based on current results.
fn recompute_form_view(
    form: &crate::form_parser::FormDefinition,
    base_dir: &std::path::Path,
    results: &std::collections::HashMap<String, Value>,
    items: &mut Vec<DisplayItem>,
    fields: &mut Vec<FieldDefinition>,
    selected_index: &mut usize,
    field_buffer: &mut String,
) -> crate::error::Result<()> {
    // Recompute visible items and fields based on current results
    let (new_items, new_fields) =
        crate::form_parser::recompute_visible_elements(form, base_dir, results)?;

    // Update items and fields
    *items = new_items;
    *fields = new_fields;

    // Reset to first visible field
    let visible_indices = get_visible_field_indices(fields, results);
    if !visible_indices.is_empty() {
        *selected_index = visible_indices[0];
        field_buffer.clear();
        load_field_buffer(field_buffer, &fields[*selected_index], results);
    } else {
        // No visible fields, shouldn't happen but handle gracefully
        *selected_index = 0;
        field_buffer.clear();
    }

    Ok(())
}

/// TUI Backend implementation using ratatui
///
/// Full ratatui implementation with custom widget state machines
/// for each field type following R-STATE-SEPARATION guideline.
pub struct RatatuiBackend {
    terminal: Arc<RwLock<Option<Terminal<CrosstermBackend<io::Stdout>>>>>,
    _guard: Option<TerminalGuard>,
}

impl RatatuiBackend {
    /// Create a new TUI backend instance
    pub fn new() -> Self {
        RatatuiBackend {
            terminal: Arc::new(RwLock::new(None)),
            _guard: None,
        }
    }
}

impl Default for RatatuiBackend {
    fn default() -> Self {
        Self::new()
    }
}

#[async_trait]
impl FormBackend for RatatuiBackend {
    /// Initialize terminal in raw mode with alternate screen buffer
    /// Implements R-GRACEFUL-SHUTDOWN pattern with TerminalGuard
    async fn initialize(&mut self) -> Result<()> {
        // Enable raw mode
        enable_raw_mode().map_err(|e| {
            ErrorWrapper::validation_failed(format!("Failed to enable raw mode: {}", e))
        })?;

        // Enter alternate screen and enable mouse capture
        execute!(
            io::stdout(),
            EnterAlternateScreen,
            event::EnableMouseCapture
        )
        .map_err(|e| {
            ErrorWrapper::validation_failed(format!("Failed to enter alternate screen: {}", e))
        })?;

        // Create terminal backend
        let backend = CrosstermBackend::new(io::stdout());
        let terminal = Terminal::new(backend).map_err(|e| {
            ErrorWrapper::validation_failed(format!("Failed to create terminal: {}", e))
        })?;

        *self.terminal.write().unwrap() = Some(terminal);
        self._guard = Some(TerminalGuard);

        Ok(())
    }

    /// Render a display item with borders, margins, and conditional logic
    /// In TUI interactive mode, display items are not rendered since form layout is continuous
    /// in the event loop. Display items are CLI-only constructs for output formatting.
    async fn render_display_item(&self, item: &DisplayItem, context: &RenderContext) -> Result<()> {
        // Check conditional rendering
        if let Some(condition) = &item.when {
            if !evaluate_condition(condition, &context.results) {
                return Ok(());
            }
        }
        // Display items not rendered in TUI mode
        Ok(())
    }

    /// Execute a field - dispatches to appropriate field type handler
    async fn execute_field(
        &self,
        field: &FieldDefinition,
        _context: &RenderContext,
    ) -> Result<Value> {
        match field.field_type {
            FieldType::Text => self.execute_text_field(field).await,
            FieldType::Confirm => self.execute_confirm_field(field).await,
            FieldType::Password => self.execute_password_field(field).await,
            FieldType::Select => self.execute_select_field(field).await,
            FieldType::MultiSelect => self.execute_multiselect_field(field).await,
            FieldType::Custom => self.execute_custom_field(field).await,
            FieldType::Editor => self.execute_editor_field(field).await,
            FieldType::Date => self.execute_date_field(field).await,
            FieldType::RepeatingGroup => self.execute_repeating_group_field(field).await,
        }
    }

    /// Execute complete form with left field list, right input, bottom buttons
    async fn execute_form_complete(
        &mut self,
        form: &crate::form_parser::FormDefinition,
        base_dir: &std::path::Path,
        mut items: Vec<DisplayItem>,
        mut fields: Vec<FieldDefinition>,
        initial_values: Option<std::collections::HashMap<String, Value>>,
    ) -> Result<std::collections::HashMap<String, Value>> {
        let mut results = initial_values.unwrap_or_default();

        // Render display items first
        for item in &items {
            self.render_display_item(
                item,
                &super::RenderContext {
                    results: Arc::new(results.clone()),
                    locale: form.locale.clone(),
                },
            )
            .await?;
        }

        let mut selected_index = 0;
        let mut focus_panel = FormPanel::FieldList;
        let mut button_focus = ButtonFocus::Submit;
        let mut field_buffer = String::new();

        // Set selected_index to first visible field
        let visible_indices = get_visible_field_indices(&fields, &results);
        if !visible_indices.is_empty() {
            selected_index = visible_indices[0];
        }

        // Load initial buffer value for first field
        load_field_buffer(&mut field_buffer, &fields[selected_index], &results);

        loop {
            // Render form with 3-panel layout
            {
                let mut terminal_ref = self.terminal.write().unwrap();
                if let Some(terminal) = terminal_ref.as_mut() {
                    let fields_clone = fields.to_vec();
                    let results_clone = results.clone();
                    let selected_index_clone = selected_index;
                    let focus_clone = focus_panel;
                    let button_clone = button_focus;
                    let buffer_clone = field_buffer.clone();

                    terminal.draw(|frame| {
                        render_form_layout(
                            frame,
                            &fields_clone,
                            &results_clone,
                            selected_index_clone,
                            focus_clone,
                            button_clone,
                            &buffer_clone,
                        );
                    })?;
                }
            }

            // Handle key input based on focus panel
            if event::poll(Duration::from_millis(100))? {
                if let Event::Key(key) = event::read()? {
                    // Global hotkeys (work in any panel)
                    match key.code {
                        KeyCode::Esc => {
                            // Cancel form with ESC key
                            return Err(ErrorWrapper::cancelled_no_context());
                        }
                        KeyCode::Char('e') if key.modifiers.contains(KeyModifiers::CONTROL) => {
                            // Exit and submit form with CTRL+E
                            if focus_panel == FormPanel::InputField {
                                let field = &fields[selected_index];
                                let current_field_type = field.field_type;

                                if !field_buffer.is_empty() {
                                    if current_field_type == FieldType::Confirm {
                                        let bool_value = field_buffer == "true";
                                        results.insert(field.name.clone(), Value::Bool(bool_value));
                                    } else {
                                        results.insert(
                                            field.name.clone(),
                                            Value::String(field_buffer.clone()),
                                        );
                                    }
                                }
                            }
                            // Finalize results with all fields and defaults
                            finalize_results(&mut results, &fields);
                            return Ok(results);
                        }
                        KeyCode::Char('q') if key.modifiers.contains(KeyModifiers::CONTROL) => {
                            // Cancel form
                            return Err(ErrorWrapper::cancelled_no_context());
                        }
                        _ => {}
                    }

                    match focus_panel {
                        FormPanel::FieldList => match key.code {
                            KeyCode::Up => {
                                // Navigate to previous visible field
                                let visible_indices = get_visible_field_indices(&fields, &results);
                                if let Some(current_pos) = visible_indices
                                    .iter()
                                    .position(|&idx| idx == selected_index)
                                {
                                    if current_pos > 0 {
                                        selected_index = visible_indices[current_pos - 1];
                                        load_field_buffer(
                                            &mut field_buffer,
                                            &fields[selected_index],
                                            &results,
                                        );
                                    }
                                }
                            }
                            KeyCode::Down => {
                                // Navigate to next visible field
                                let visible_indices = get_visible_field_indices(&fields, &results);
                                if let Some(current_pos) = visible_indices
                                    .iter()
                                    .position(|&idx| idx == selected_index)
                                {
                                    if current_pos < visible_indices.len() - 1 {
                                        selected_index = visible_indices[current_pos + 1];
                                        load_field_buffer(
                                            &mut field_buffer,
                                            &fields[selected_index],
                                            &results,
                                        );
                                    }
                                }
                            }
                            KeyCode::Tab | KeyCode::Right => {
                                // Check if current field is RepeatingGroup
                                if fields[selected_index].field_type == FieldType::RepeatingGroup {
                                    // Execute RepeatingGroup handler instead of switching to InputField
                                    let field_clone = fields[selected_index].clone();
                                    let value =
                                        self.execute_repeating_group_field(&field_clone).await?;
                                    results.insert(field_clone.name.clone(), value);

                                    // Reactive re-render
                                    recompute_form_view(
                                        form,
                                        base_dir,
                                        &results,
                                        &mut items,
                                        &mut fields,
                                        &mut selected_index,
                                        &mut field_buffer,
                                    )?;

                                    // Stay in FieldList panel (will re-render on next loop)
                                } else {
                                    focus_panel = FormPanel::InputField;
                                }
                            }
                            KeyCode::Enter => {
                                // Check if current field is RepeatingGroup
                                if fields[selected_index].field_type == FieldType::RepeatingGroup {
                                    // Execute RepeatingGroup handler instead of switching to InputField
                                    let field_clone = fields[selected_index].clone();
                                    let value =
                                        self.execute_repeating_group_field(&field_clone).await?;
                                    results.insert(field_clone.name.clone(), value);

                                    // Reactive re-render
                                    recompute_form_view(
                                        form,
                                        base_dir,
                                        &results,
                                        &mut items,
                                        &mut fields,
                                        &mut selected_index,
                                        &mut field_buffer,
                                    )?;

                                    // Stay in FieldList panel
                                } else {
                                    focus_panel = FormPanel::InputField;
                                }
                            }
                            _ => {}
                        },
                        FormPanel::InputField => {
                            let current_field_type = fields[selected_index].field_type;

                            // Handle Select/MultiSelect fields with arrow navigation
                            if current_field_type == FieldType::Select
                                || current_field_type == FieldType::MultiSelect
                            {
                                if !fields[selected_index].options.is_empty() {
                                    let options = &fields[selected_index].options;
                                    match key.code {
                                        KeyCode::Up => {
                                            // Navigate to previous option
                                            let current_idx = options
                                                .iter()
                                                .position(|o| o.value == field_buffer)
                                                .unwrap_or(0);
                                            if current_idx > 0 {
                                                field_buffer =
                                                    options[current_idx - 1].value.clone();
                                            }
                                        }
                                        KeyCode::Down => {
                                            // Navigate to next option
                                            let current_idx = options
                                                .iter()
                                                .position(|o| o.value == field_buffer)
                                                .unwrap_or(0);
                                            if current_idx < options.len() - 1 {
                                                field_buffer =
                                                    options[current_idx + 1].value.clone();
                                            }
                                        }
                                        KeyCode::Char(c) => {
                                            // Search by first letter
                                            let search_char = c.to_lowercase().to_string();
                                            if let Some(found) = options.iter().find(|o| {
                                                o.value.to_lowercase().starts_with(&search_char)
                                            }) {
                                                field_buffer = found.value.clone();
                                            }
                                        }
                                        KeyCode::Tab | KeyCode::Right => {
                                            focus_panel = FormPanel::Buttons;
                                            button_focus = ButtonFocus::Submit;
                                        }
                                        KeyCode::Left => {
                                            focus_panel = FormPanel::FieldList;
                                        }
                                        KeyCode::Enter => {
                                            // Save field value
                                            let field = &fields[selected_index];
                                            results.insert(
                                                field.name.clone(),
                                                Value::String(field_buffer.clone()),
                                            );

                                            // Reactive re-render: update visible items/fields based on new results
                                            recompute_form_view(
                                                form,
                                                base_dir,
                                                &results,
                                                &mut items,
                                                &mut fields,
                                                &mut selected_index,
                                                &mut field_buffer,
                                            )?;

                                            focus_panel = FormPanel::FieldList;
                                        }
                                        KeyCode::Esc => {
                                            // Discard changes, reload from results
                                            let field = &fields[selected_index];
                                            load_field_buffer(&mut field_buffer, field, &results);
                                            focus_panel = FormPanel::FieldList;
                                        }
                                        _ => {}
                                    }
                                }
                            } else if current_field_type == FieldType::Password {
                                // Password field input (same as text but characters are masked in display)
                                match key.code {
                                    KeyCode::Char(c) => {
                                        field_buffer.push(c);
                                    }
                                    KeyCode::Backspace => {
                                        field_buffer.pop();
                                    }
                                    KeyCode::Tab | KeyCode::Right => {
                                        focus_panel = FormPanel::Buttons;
                                        button_focus = ButtonFocus::Submit;
                                    }
                                    KeyCode::Left => {
                                        focus_panel = FormPanel::FieldList;
                                    }
                                    KeyCode::Enter => {
                                        // Save field value
                                        let field = &fields[selected_index];
                                        results.insert(
                                            field.name.clone(),
                                            Value::String(field_buffer.clone()),
                                        );

                                        // Reactive re-render: update visible items/fields based on new results
                                        recompute_form_view(
                                            form,
                                            base_dir,
                                            &results,
                                            &mut items,
                                            &mut fields,
                                            &mut selected_index,
                                            &mut field_buffer,
                                        )?;

                                        focus_panel = FormPanel::FieldList;
                                    }
                                    KeyCode::Esc => {
                                        // Discard changes, reload from results
                                        let field = &fields[selected_index];
                                        load_field_buffer(&mut field_buffer, field, &results);
                                        focus_panel = FormPanel::FieldList;
                                    }
                                    _ => {}
                                }
                            } else if current_field_type == FieldType::Confirm {
                                // Handle Confirm (boolean) field
                                match key.code {
                                    KeyCode::Char('y') | KeyCode::Char('Y') => {
                                        field_buffer = "true".to_string();
                                    }
                                    KeyCode::Char('n') | KeyCode::Char('N') => {
                                        field_buffer = "false".to_string();
                                    }
                                    KeyCode::Char(' ') => {
                                        // Toggle on space
                                        field_buffer = if field_buffer == "true" {
                                            "false".to_string()
                                        } else {
                                            "true".to_string()
                                        };
                                    }
                                    KeyCode::Tab | KeyCode::Right => {
                                        focus_panel = FormPanel::Buttons;
                                        button_focus = ButtonFocus::Submit;
                                    }
                                    KeyCode::Left => {
                                        focus_panel = FormPanel::FieldList;
                                    }
                                    KeyCode::Enter => {
                                        // Save field value as boolean
                                        let field = &fields[selected_index];
                                        let bool_value = field_buffer == "true";
                                        results.insert(field.name.clone(), Value::Bool(bool_value));

                                        // Reactive re-render: update visible items/fields based on new results
                                        recompute_form_view(
                                            form,
                                            base_dir,
                                            &results,
                                            &mut items,
                                            &mut fields,
                                            &mut selected_index,
                                            &mut field_buffer,
                                        )?;

                                        focus_panel = FormPanel::FieldList;
                                    }
                                    KeyCode::Esc => {
                                        // Discard changes, reload from results
                                        let field = &fields[selected_index];
                                        load_field_buffer(&mut field_buffer, field, &results);
                                        focus_panel = FormPanel::FieldList;
                                    }
                                    _ => {}
                                }
                            } else {
                                // Text and other field types
                                match key.code {
                                    KeyCode::Char(c) => {
                                        field_buffer.push(c);
                                    }
                                    KeyCode::Backspace => {
                                        field_buffer.pop();
                                    }
                                    KeyCode::Tab | KeyCode::Right => {
                                        focus_panel = FormPanel::Buttons;
                                        button_focus = ButtonFocus::Submit;
                                    }
                                    KeyCode::Left => {
                                        focus_panel = FormPanel::FieldList;
                                    }
                                    KeyCode::Enter => {
                                        // Save field value
                                        let field = &fields[selected_index];
                                        results.insert(
                                            field.name.clone(),
                                            Value::String(field_buffer.clone()),
                                        );

                                        // Reactive re-render: update visible items/fields based on new results
                                        recompute_form_view(
                                            form,
                                            base_dir,
                                            &results,
                                            &mut items,
                                            &mut fields,
                                            &mut selected_index,
                                            &mut field_buffer,
                                        )?;

                                        focus_panel = FormPanel::FieldList;
                                    }
                                    KeyCode::Esc => {
                                        // Discard changes, reload from results
                                        let field = &fields[selected_index];
                                        load_field_buffer(&mut field_buffer, field, &results);
                                        focus_panel = FormPanel::FieldList;
                                    }
                                    _ => {}
                                }
                            }
                        }
                        FormPanel::Buttons => match key.code {
                            KeyCode::Left | KeyCode::Tab => {
                                button_focus = if button_focus == ButtonFocus::Submit {
                                    ButtonFocus::Cancel
                                } else {
                                    ButtonFocus::Submit
                                };
                            }
                            KeyCode::Right => {
                                button_focus = if button_focus == ButtonFocus::Cancel {
                                    ButtonFocus::Submit
                                } else {
                                    ButtonFocus::Cancel
                                };
                            }
                            KeyCode::Up => {
                                focus_panel = FormPanel::InputField;
                            }
                            KeyCode::Enter => match button_focus {
                                ButtonFocus::Submit => {
                                    finalize_results(&mut results, &fields);
                                    return Ok(results);
                                }
                                ButtonFocus::Cancel => {
                                    return Err(ErrorWrapper::cancelled_no_context())
                                }
                            },
                            _ => {}
                        },
                    }
                }
            }
        }
    }

    fn as_any(&self) -> &dyn std::any::Any {
        self
    }

    /// Shutdown terminal - cleanup happens via Drop trait on _guard
    async fn shutdown(&mut self) -> Result<()> {
        *self.terminal.write().unwrap() = None;
        self._guard = None;
        Ok(())
    }

    fn is_available() -> bool {
        atty::is(atty::Stream::Stdout)
    }

    fn name(&self) -> &str {
        "tui"
    }
}

impl RatatuiBackend {
    /// Execute text input field with cursor and edit support
    /// Implements R-STATE-SEPARATION: TextInputState owns buffer, separate render logic
    async fn execute_text_field(&self, field: &FieldDefinition) -> Result<Value> {
        let mut state = TextInputState {
            buffer: String::new(),
            cursor_pos: 0,
        };

        loop {
            // Render current state
            {
                let mut terminal_ref = self.terminal.write().unwrap();
                if let Some(terminal) = terminal_ref.as_mut() {
                    let buffer_clone = state.buffer.clone();
                    let prompt = field.prompt.clone();
                    let placeholder = field.placeholder.as_ref().cloned().unwrap_or_default();

                    terminal
                        .draw(|frame| {
                            let area = frame.area();
                            let display_text = if buffer_clone.is_empty() && !placeholder.is_empty()
                            {
                                format!("{}: {} ", prompt, placeholder)
                            } else if buffer_clone.is_empty() {
                                format!("{}: [_] ", prompt)
                            } else {
                                format!("{}: {} ", prompt, buffer_clone)
                            };

                            let paragraph = Paragraph::new(display_text)
                                .block(Block::default().borders(Borders::ALL));

                            frame.render_widget(paragraph, area);
                        })
                        .map_err(|e| {
                            ErrorWrapper::validation_failed(format!("Failed to render: {}", e))
                        })?;
                } else {
                    return Err(ErrorWrapper::validation_failed("Terminal not initialized"));
                }
            }

            // Non-blocking event loop (R-EVENT-LOOP: 100ms poll)
            if event::poll(Duration::from_millis(100))
                .map_err(|e| ErrorWrapper::validation_failed(format!("Poll failed: {}", e)))?
            {
                if let Event::Key(key) = event::read()
                    .map_err(|e| ErrorWrapper::validation_failed(format!("Read failed: {}", e)))?
                {
                    match key.code {
                        KeyCode::Char(c) => {
                            state.buffer.insert(state.cursor_pos, c);
                            state.cursor_pos += 1;
                        }
                        KeyCode::Backspace => {
                            if state.cursor_pos > 0 {
                                state.buffer.remove(state.cursor_pos - 1);
                                state.cursor_pos -= 1;
                            }
                        }
                        KeyCode::Delete => {
                            if state.cursor_pos < state.buffer.len() {
                                state.buffer.remove(state.cursor_pos);
                            }
                        }
                        KeyCode::Left => {
                            if state.cursor_pos > 0 {
                                state.cursor_pos -= 1;
                            }
                        }
                        KeyCode::Right => {
                            if state.cursor_pos < state.buffer.len() {
                                state.cursor_pos += 1;
                            }
                        }
                        KeyCode::Home => state.cursor_pos = 0,
                        KeyCode::End => state.cursor_pos = state.buffer.len(),
                        KeyCode::Enter => {
                            if field.required.unwrap_or(false) && state.buffer.is_empty() {
                                continue;
                            }
                            return Ok(json!(state.buffer.clone()));
                        }
                        KeyCode::Esc => return Err(ErrorWrapper::cancelled_no_context()),
                        _ => {}
                    }
                }
            }
        }
    }

    /// Execute confirm (yes/no) field
    /// Simple boolean state machine with space/arrow key toggling
    async fn execute_confirm_field(&self, field: &FieldDefinition) -> Result<Value> {
        let mut state = ConfirmState {
            value: field
                .default
                .as_deref()
                .map(|d| d == "true")
                .unwrap_or(false),
        };

        loop {
            // Render current state
            {
                let mut terminal_ref = self.terminal.write().unwrap();
                if let Some(terminal) = terminal_ref.as_mut() {
                    let value = state.value;
                    let prompt = field.prompt.clone();

                    terminal
                        .draw(|frame| {
                            let area = frame.area();
                            let yes_style = if value { " ✓ YES " } else { "   yes   " };
                            let no_style = if !value { " ✗ NO  " } else { "   no    " };
                            let display_text = format!("{}: {} / {}", prompt, yes_style, no_style);

                            let paragraph = Paragraph::new(display_text)
                                .block(Block::default().borders(Borders::ALL));

                            frame.render_widget(paragraph, area);
                        })
                        .map_err(|e| {
                            ErrorWrapper::validation_failed(format!("Failed to render: {}", e))
                        })?;
                } else {
                    return Err(ErrorWrapper::validation_failed("Terminal not initialized"));
                }
            }

            // Event loop
            if event::poll(Duration::from_millis(100))
                .map_err(|e| ErrorWrapper::validation_failed(format!("Poll failed: {}", e)))?
            {
                if let Event::Key(key) = event::read()
                    .map_err(|e| ErrorWrapper::validation_failed(format!("Read failed: {}", e)))?
                {
                    match key.code {
                        KeyCode::Char('y') | KeyCode::Char('Y') => {
                            state.value = true;
                        }
                        KeyCode::Char('n') | KeyCode::Char('N') => {
                            state.value = false;
                        }
                        KeyCode::Char(' ') | KeyCode::Left | KeyCode::Right => {
                            state.value = !state.value;
                        }
                        KeyCode::Enter => return Ok(json!(state.value)),
                        KeyCode::Esc => return Err(ErrorWrapper::cancelled_no_context()),
                        _ => {}
                    }
                }
            }
        }
    }

    /// Execute password input field with optional visibility toggle
    /// Masks input with bullets, Ctrl+R toggles visibility
    async fn execute_password_field(&self, field: &FieldDefinition) -> Result<Value> {
        let mut state = PasswordInputState {
            buffer: String::new(),
            visible: false,
            with_toggle: field.placeholder.as_deref() == Some("toggle"),
        };

        loop {
            // Render current state
            {
                let mut terminal_ref = self.terminal.write().unwrap();
                if let Some(terminal) = terminal_ref.as_mut() {
                    let buffer_clone = state.buffer.clone();
                    let visible = state.visible;
                    let with_toggle = state.with_toggle;
                    let prompt = field.prompt.clone();

                    terminal
                        .draw(|frame| {
                            let area = frame.area();
                            let display_value = if visible {
                                buffer_clone.clone()
                            } else {
                                "•".repeat(buffer_clone.len())
                            };
                            let display_text = if with_toggle && buffer_clone.is_empty() {
                                format!("{}: [_] (Ctrl+R to toggle)", prompt)
                            } else if with_toggle {
                                format!("{}: {} (Ctrl+R to toggle)", prompt, display_value)
                            } else {
                                format!("{}: {}", prompt, display_value)
                            };

                            let paragraph = Paragraph::new(display_text)
                                .block(Block::default().borders(Borders::ALL));

                            frame.render_widget(paragraph, area);
                        })
                        .map_err(|e| {
                            ErrorWrapper::validation_failed(format!("Failed to render: {}", e))
                        })?;
                } else {
                    return Err(ErrorWrapper::validation_failed("Terminal not initialized"));
                }
            }

            // Event loop
            if event::poll(Duration::from_millis(100))
                .map_err(|e| ErrorWrapper::validation_failed(format!("Poll failed: {}", e)))?
            {
                if let Event::Key(key) = event::read()
                    .map_err(|e| ErrorWrapper::validation_failed(format!("Read failed: {}", e)))?
                {
                    match key.code {
                        KeyCode::Char('r') if key.modifiers.contains(KeyModifiers::CONTROL) => {
                            if state.with_toggle {
                                state.visible = !state.visible;
                            }
                        }
                        KeyCode::Char(c) => {
                            state.buffer.push(c);
                        }
                        KeyCode::Backspace => {
                            state.buffer.pop();
                        }
                        KeyCode::Enter => {
                            if field.required.unwrap_or(false) && state.buffer.is_empty() {
                                continue;
                            }
                            return Ok(json!(state.buffer.clone()));
                        }
                        KeyCode::Esc => return Err(ErrorWrapper::cancelled_no_context()),
                        _ => {}
                    }
                }
            }
        }
    }

    /// Execute select (single choice) field with pagination support
    /// Implements pagination and navigation with Up/Down arrows
    async fn execute_select_field(&self, field: &FieldDefinition) -> Result<Value> {
        if field.options.is_empty() {
            return Err(ErrorWrapper::validation_failed(
                "Select field must have options",
            ));
        }

        let page_size = field.page_size.unwrap_or(5);
        let options_strings: Vec<String> =
            field.options.iter().map(|opt| opt.as_string()).collect();
        let mut state = SelectState {
            options: options_strings,
            selected_index: 0,
            scroll_offset: 0,
            page_size,
            vim_mode: field.vim_mode.unwrap_or(false),
        };

        loop {
            // Render current state
            {
                let mut terminal_ref = self.terminal.write().unwrap();
                if let Some(terminal) = terminal_ref.as_mut() {
                    let options_clone = state.options.clone();
                    let selected_index = state.selected_index;
                    let scroll_offset = state.scroll_offset;
                    let page_size = state.page_size;
                    let prompt = field.prompt.clone();

                    terminal
                        .draw(|frame| {
                            let area = frame.area();

                            let mut display_lines =
                                vec![format!("{}: (Use arrow keys to navigate)", prompt)];
                            for (i, option) in options_clone
                                .iter()
                                .enumerate()
                                .skip(scroll_offset)
                                .take(page_size)
                            {
                                let prefix = if i == selected_index { "▶ " } else { "  " };
                                let style = if i == selected_index {
                                    " [SELECTED]"
                                } else {
                                    ""
                                };
                                display_lines.push(format!("{}{}{}", prefix, option, style));
                            }
                            display_lines.push(format!(
                                "({}/{})",
                                selected_index + 1,
                                options_clone.len()
                            ));

                            let text = display_lines.join("\n");
                            let paragraph =
                                Paragraph::new(text).block(Block::default().borders(Borders::ALL));

                            frame.render_widget(paragraph, area);
                        })
                        .map_err(|e| {
                            ErrorWrapper::validation_failed(format!("Failed to render: {}", e))
                        })?;
                } else {
                    return Err(ErrorWrapper::validation_failed("Terminal not initialized"));
                }
            }

            // Event loop with vim mode prep
            if event::poll(Duration::from_millis(100))
                .map_err(|e| ErrorWrapper::validation_failed(format!("Poll failed: {}", e)))?
            {
                if let Event::Key(key) = event::read()
                    .map_err(|e| ErrorWrapper::validation_failed(format!("Read failed: {}", e)))?
                {
                    let max_idx = state.options.len().saturating_sub(1);
                    match key.code {
                        KeyCode::Down => {
                            if state.selected_index < max_idx {
                                state.selected_index += 1;
                                if state.selected_index >= state.scroll_offset + state.page_size {
                                    state.scroll_offset =
                                        (state.selected_index - state.page_size + 1).max(0);
                                }
                            }
                        }
                        KeyCode::Up => {
                            if state.selected_index > 0 {
                                state.selected_index -= 1;
                                if state.selected_index < state.scroll_offset {
                                    state.scroll_offset = state.selected_index;
                                }
                            }
                        }
                        KeyCode::Char('j') if state.vim_mode => {
                            if state.selected_index < max_idx {
                                state.selected_index += 1;
                                if state.selected_index >= state.scroll_offset + state.page_size {
                                    state.scroll_offset =
                                        (state.selected_index - state.page_size + 1).max(0);
                                }
                            }
                        }
                        KeyCode::Char('k') if state.vim_mode => {
                            if state.selected_index > 0 {
                                state.selected_index -= 1;
                                if state.selected_index < state.scroll_offset {
                                    state.scroll_offset = state.selected_index;
                                }
                            }
                        }
                        KeyCode::Enter => {
                            return Ok(json!(state.options[state.selected_index].clone()));
                        }
                        KeyCode::Esc => return Err(ErrorWrapper::cancelled_no_context()),
                        _ => {}
                    }
                }
            }
        }
    }

    /// Execute multiselect field with checkboxes
    /// Allows selecting multiple options with Space, confirm with Enter
    async fn execute_multiselect_field(&self, field: &FieldDefinition) -> Result<Value> {
        if field.options.is_empty() {
            return Err(ErrorWrapper::validation_failed(
                "MultiSelect field must have options",
            ));
        }

        let page_size = field.page_size.unwrap_or(5);
        let options_strings: Vec<String> =
            field.options.iter().map(|opt| opt.as_string()).collect();
        let mut state = MultiSelectState {
            options: options_strings,
            selected: vec![false; field.options.len()],
            cursor_index: 0,
            scroll_offset: 0,
            page_size,
            vim_mode: field.vim_mode.unwrap_or(false),
        };

        loop {
            // Render current state
            {
                let mut terminal_ref = self.terminal.write().unwrap();
                if let Some(terminal) = terminal_ref.as_mut() {
                    let options_clone = state.options.clone();
                    let selected = state.selected.clone();
                    let cursor_index = state.cursor_index;
                    let scroll_offset = state.scroll_offset;
                    let page_size = state.page_size;
                    let prompt = field.prompt.clone();

                    terminal
                        .draw(|frame| {
                            let area = frame.area();
                            let mut display_lines =
                                vec![format!("{}: (Space to toggle, Enter to confirm)", prompt)];

                            for (i, option) in options_clone
                                .iter()
                                .enumerate()
                                .skip(scroll_offset)
                                .take(page_size)
                            {
                                let checkbox = if selected[i] { "[✓]" } else { "[ ]" };
                                let prefix = if i == cursor_index { "▶ " } else { "  " };
                                display_lines.push(format!("{}{} {}", prefix, checkbox, option));
                            }

                            let selected_count = selected.iter().filter(|&&s| s).count();
                            display_lines.push(format!(
                                "Selected: {}/{}",
                                selected_count,
                                options_clone.len()
                            ));

                            let text = display_lines.join("\n");
                            let paragraph =
                                Paragraph::new(text).block(Block::default().borders(Borders::ALL));

                            frame.render_widget(paragraph, area);
                        })
                        .map_err(|e| {
                            ErrorWrapper::validation_failed(format!("Failed to render: {}", e))
                        })?;
                } else {
                    return Err(ErrorWrapper::validation_failed("Terminal not initialized"));
                }
            }

            // Event loop
            if event::poll(Duration::from_millis(100))
                .map_err(|e| ErrorWrapper::validation_failed(format!("Poll failed: {}", e)))?
            {
                if let Event::Key(key) = event::read()
                    .map_err(|e| ErrorWrapper::validation_failed(format!("Read failed: {}", e)))?
                {
                    let max_idx = state.options.len().saturating_sub(1);
                    match key.code {
                        KeyCode::Down => {
                            if state.cursor_index < max_idx {
                                state.cursor_index += 1;
                                if state.cursor_index >= state.scroll_offset + state.page_size {
                                    state.scroll_offset =
                                        (state.cursor_index - state.page_size + 1).max(0);
                                }
                            }
                        }
                        KeyCode::Up => {
                            if state.cursor_index > 0 {
                                state.cursor_index -= 1;
                                if state.cursor_index < state.scroll_offset {
                                    state.scroll_offset = state.cursor_index;
                                }
                            }
                        }
                        KeyCode::Char('j') if state.vim_mode => {
                            if state.cursor_index < max_idx {
                                state.cursor_index += 1;
                                if state.cursor_index >= state.scroll_offset + state.page_size {
                                    state.scroll_offset =
                                        (state.cursor_index - state.page_size + 1).max(0);
                                }
                            }
                        }
                        KeyCode::Char('k') if state.vim_mode => {
                            if state.cursor_index > 0 {
                                state.cursor_index -= 1;
                                if state.cursor_index < state.scroll_offset {
                                    state.scroll_offset = state.cursor_index;
                                }
                            }
                        }
                        KeyCode::Char(' ') => {
                            state.selected[state.cursor_index] =
                                !state.selected[state.cursor_index];
                        }
                        KeyCode::Enter => {
                            let selected_items: Vec<String> = state
                                .options
                                .iter()
                                .enumerate()
                                .filter_map(|(i, opt)| {
                                    if state.selected[i] {
                                        Some(opt.clone())
                                    } else {
                                        None
                                    }
                                })
                                .collect();
                            return Ok(json!(selected_items));
                        }
                        KeyCode::Esc => return Err(ErrorWrapper::cancelled_no_context()),
                        _ => {}
                    }
                }
            }
        }
    }

    /// Execute custom type field with type-specific validation
    /// Supports i32, f64, ipv4, ipv6, uuid, and other parseable types
    async fn execute_custom_field(&self, field: &FieldDefinition) -> Result<Value> {
        let custom_type = field.custom_type.as_deref().unwrap_or("String");
        let mut state = TextInputState {
            buffer: String::new(),
            cursor_pos: 0,
        };

        loop {
            // Render current state with type hint
            {
                let mut terminal_ref = self.terminal.write().unwrap();
                if let Some(terminal) = terminal_ref.as_mut() {
                    let buffer_clone = state.buffer.clone();
                    let prompt = field.prompt.clone();
                    let placeholder = field.placeholder.clone().unwrap_or_default();

                    terminal
                        .draw(|frame| {
                            let area = frame.area();
                            let display_text = if buffer_clone.is_empty() && !placeholder.is_empty()
                            {
                                format!("{} ({}): {} ", prompt, custom_type, placeholder)
                            } else if buffer_clone.is_empty() {
                                format!("{} ({}): [_] ", prompt, custom_type)
                            } else {
                                format!("{} ({}): {} ", prompt, custom_type, buffer_clone)
                            };

                            let paragraph = Paragraph::new(display_text)
                                .block(Block::default().borders(Borders::ALL));

                            frame.render_widget(paragraph, area);
                        })
                        .map_err(|e| {
                            ErrorWrapper::validation_failed(format!("Failed to render: {}", e))
                        })?;
                } else {
                    return Err(ErrorWrapper::validation_failed("Terminal not initialized"));
                }
            }

            // Event loop
            if event::poll(Duration::from_millis(100))
                .map_err(|e| ErrorWrapper::validation_failed(format!("Poll failed: {}", e)))?
            {
                if let Event::Key(key) = event::read()
                    .map_err(|e| ErrorWrapper::validation_failed(format!("Read failed: {}", e)))?
                {
                    match key.code {
                        KeyCode::Char(c) => {
                            state.buffer.insert(state.cursor_pos, c);
                            state.cursor_pos += 1;
                        }
                        KeyCode::Backspace => {
                            if state.cursor_pos > 0 {
                                state.cursor_pos -= 1;
                                state.buffer.remove(state.cursor_pos);
                            }
                        }
                        KeyCode::Left => {
                            state.cursor_pos = state.cursor_pos.saturating_sub(1);
                        }
                        KeyCode::Right => {
                            if state.cursor_pos < state.buffer.len() {
                                state.cursor_pos += 1;
                            }
                        }
                        KeyCode::Home => state.cursor_pos = 0,
                        KeyCode::End => state.cursor_pos = state.buffer.len(),
                        KeyCode::Enter => {
                            // Validate based on custom type
                            let validation_result =
                                validate_custom_type(&state.buffer, custom_type);
                            if let Err(e) = validation_result {
                                // Show error overlay
                                self.show_validation_error(&format!(
                                    "Invalid {}: {}",
                                    custom_type, e
                                ))
                                .await?;
                                continue;
                            }

                            // Return validated value (convert to appropriate type)
                            let value = parse_custom_value(&state.buffer, custom_type);
                            return Ok(value);
                        }
                        KeyCode::Esc => return Err(ErrorWrapper::cancelled_no_context()),
                        _ => {}
                    }
                }
            }
        }
    }

    /// Execute repeating group field with split-pane list/preview UI
    /// Allows add/edit/delete operations on array items using fragments
    async fn execute_repeating_group_field(&self, field: &FieldDefinition) -> Result<Value> {
        use ratatui::{
            layout::{Constraint, Direction, Layout},
            text::{Line, Span},
            widgets::{List, ListItem, ListState},
        };

        let fragment_path = field.fragment.as_ref().ok_or_else(|| {
            ErrorWrapper::form_parse_failed("RepeatingGroup requires 'fragment' field")
        })?;

        let min_items = field.min_items.unwrap_or(0);
        let max_items = field.max_items.unwrap_or(usize::MAX);

        let mut items: Vec<HashMap<String, Value>> = Vec::new();
        let mut selected_index: usize = 0;
        let mut list_state = ListState::default();
        list_state.select(Some(0));

        loop {
            // Render UI in separate scope to ensure terminal_ref is dropped
            {
                let mut terminal_ref = self.terminal.write().unwrap();
                if let Some(terminal) = terminal_ref.as_mut() {
                    let current_items = items.clone();
                    let item_count = current_items.len();
                    let selected_idx = selected_index;
                    let min = min_items;
                    let max = max_items;
                    let field_prompt = field.prompt.clone();

                    terminal
                        .draw(|frame| {
                            let area = frame.area();

                            // Split screen: left=list, right=preview
                            let chunks = Layout::default()
                                .direction(Direction::Horizontal)
                                .constraints([
                                    Constraint::Percentage(50),
                                    Constraint::Percentage(50),
                                ])
                                .split(area);

                            // Left panel: List of items with actions
                            let mut list_items_vec = Vec::new();

                            // Add action items
                            if item_count < max {
                                list_items_vec.push(ListItem::new(Line::from(vec![
                                    Span::styled("[A] ", Style::default().fg(Color::Green)),
                                    Span::raw("Add new item"),
                                ])));
                            }

                            if !current_items.is_empty() {
                                list_items_vec.push(ListItem::new(Line::from(vec![
                                    Span::styled("[E] ", Style::default().fg(Color::Yellow)),
                                    Span::raw("Edit item"),
                                ])));
                                list_items_vec.push(ListItem::new(Line::from(vec![
                                    Span::styled("[D] ", Style::default().fg(Color::Red)),
                                    Span::raw("Delete item"),
                                ])));
                            }

                            if item_count >= min {
                                list_items_vec.push(ListItem::new(Line::from(vec![
                                    Span::styled("[Enter] ", Style::default().fg(Color::Blue)),
                                    Span::raw("Continue to next field"),
                                ])));
                            }

                            // Add separator
                            list_items_vec.push(ListItem::new(""));
                            list_items_vec.push(ListItem::new(Line::from(vec![Span::styled(
                                "Items:",
                                Style::default().add_modifier(Modifier::BOLD),
                            )])));

                            // Add existing items
                            for (i, item) in current_items.iter().enumerate() {
                                let summary = Self::summarize_item_tui(item);
                                let style = if i == selected_idx && !current_items.is_empty() {
                                    Style::default()
                                        .fg(Color::Cyan)
                                        .add_modifier(Modifier::BOLD)
                                } else {
                                    Style::default()
                                };
                                list_items_vec.push(ListItem::new(Line::from(vec![
                                    Span::styled(format!("  #{} ", i + 1), style),
                                    Span::styled(summary, style),
                                ])));
                            }

                            let status_msg = if min > 0 && item_count < min {
                                format!(" - minimum {} required", min)
                            } else {
                                String::new()
                            };

                            let list_title =
                                format!("{} ({} items){}", field_prompt, item_count, status_msg);

                            let list = List::new(list_items_vec)
                                .block(Block::default().borders(Borders::ALL).title(list_title));

                            frame.render_widget(list, chunks[0]);

                            // Right panel: Preview of selected item
                            let preview_text = if !current_items.is_empty()
                                && selected_idx < current_items.len()
                            {
                                let item = &current_items[selected_idx];
                                let mut lines = vec![
                                    format!("Item #{} Details", selected_idx + 1),
                                    "─".repeat(30),
                                ];
                                for (key, value) in item {
                                    lines.push(format!(
                                        "{}: {}",
                                        key,
                                        Self::format_value_preview(value)
                                    ));
                                }
                                lines.join("\n")
                            } else if current_items.is_empty() {
                                String::from("No items yet\n\nPress 'A' to add an item")
                            } else {
                                String::from("Select an item to preview")
                            };

                            let preview = Paragraph::new(preview_text)
                                .block(Block::default().borders(Borders::ALL).title("Preview"));

                            frame.render_widget(preview, chunks[1]);
                        })
                        .map_err(|e| {
                            ErrorWrapper::validation_failed(format!("Render failed: {}", e))
                        })?;
                }
            } // terminal_ref dropped here

            // Handle keyboard events
            if event::poll(Duration::from_millis(100))
                .map_err(|e| ErrorWrapper::validation_failed(format!("Poll failed: {}", e)))?
            {
                if let Event::Key(key) = event::read()
                    .map_err(|e| ErrorWrapper::validation_failed(format!("Read failed: {}", e)))?
                {
                    match key.code {
                        KeyCode::Char('a') | KeyCode::Char('A') => {
                            if items.len() >= max_items {
                                self.show_validation_error(&format!(
                                    "Maximum {} items reached",
                                    max_items
                                ))
                                .await?;
                                continue;
                            }

                            // Execute fragment to add new item
                            match self
                                .execute_fragment_for_item(fragment_path, items.len() + 1)
                                .await
                            {
                                Ok(item_data) => {
                                    // Check for duplicates if unique constraint is set
                                    if field.unique.unwrap_or(false)
                                        && Self::is_duplicate(&item_data, &items, None)
                                    {
                                        self.show_validation_error(
                                            "This item already exists. Duplicates not allowed.",
                                        )
                                        .await?;
                                        continue;
                                    }
                                    items.push(item_data);
                                    selected_index = items.len().saturating_sub(1);
                                }
                                Err(e) if e.is_cancelled() => {
                                    // User cancelled, continue loop
                                }
                                Err(e) => {
                                    self.show_validation_error(&format!(
                                        "Error adding item: {}",
                                        e
                                    ))
                                    .await?;
                                }
                            }
                        }
                        KeyCode::Char('e') | KeyCode::Char('E') => {
                            if items.is_empty() {
                                self.show_validation_error("No items to edit").await?;
                                continue;
                            }

                            // Execute fragment to edit selected item
                            match self
                                .execute_fragment_for_item(fragment_path, selected_index + 1)
                                .await
                            {
                                Ok(updated_data) => {
                                    // Check for duplicates if unique constraint is set (exclude current item)
                                    if field.unique.unwrap_or(false)
                                        && Self::is_duplicate(
                                            &updated_data,
                                            &items,
                                            Some(selected_index),
                                        )
                                    {
                                        self.show_validation_error(
                                            "This item already exists. Duplicates not allowed.",
                                        )
                                        .await?;
                                        continue;
                                    }
                                    items[selected_index] = updated_data;
                                }
                                Err(e) if e.is_cancelled() => {
                                    // User cancelled, continue loop
                                }
                                Err(e) => {
                                    self.show_validation_error(&format!(
                                        "Error editing item: {}",
                                        e
                                    ))
                                    .await?;
                                }
                            }
                        }
                        KeyCode::Char('d') | KeyCode::Char('D') => {
                            if items.is_empty() {
                                self.show_validation_error("No items to delete").await?;
                                continue;
                            }

                            items.remove(selected_index);
                            if selected_index >= items.len() && selected_index > 0 {
                                selected_index = items.len().saturating_sub(1);
                            }
                        }
                        KeyCode::Up => {
                            if !items.is_empty() && selected_index > 0 {
                                selected_index -= 1;
                            }
                        }
                        KeyCode::Down => {
                            if !items.is_empty() && selected_index < items.len() - 1 {
                                selected_index += 1;
                            }
                        }
                        KeyCode::Enter => {
                            if items.len() < min_items {
                                self.show_validation_error(&format!(
                                    "Minimum {} items required",
                                    min_items
                                ))
                                .await?;
                                continue;
                            }
                            return Ok(json!(items));
                        }
                        KeyCode::Esc => return Err(ErrorWrapper::cancelled_no_context()),
                        _ => {}
                    }
                }
            }
        }
    }

    /// Execute a fragment to collect data for one array item
    async fn execute_fragment_for_item(
        &self,
        fragment_path: &str,
        item_number: usize,
    ) -> Result<HashMap<String, Value>> {
        // Load fragment form
        let fragment_form = crate::form_parser::load_fragment_form(fragment_path)?;

        // Show header in separate scope
        {
            let mut terminal_ref = self.terminal.write().unwrap();
            if let Some(terminal) = terminal_ref.as_mut() {
                let header_text = format!("--- Item #{} ---", item_number);
                terminal
                    .draw(|frame| {
                        let area = frame.area();
                        let paragraph = Paragraph::new(header_text)
                            .block(Block::default().borders(Borders::ALL).title("Editing Item"));
                        frame.render_widget(paragraph, area);
                    })
                    .map_err(|e| {
                        ErrorWrapper::validation_failed(format!("Render failed: {}", e))
                    })?;
            }
        } // terminal_ref dropped here

        // Wait for key press to continue
        loop {
            if event::poll(Duration::from_millis(100))
                .map_err(|e| ErrorWrapper::validation_failed(format!("Poll failed: {}", e)))?
            {
                if let Event::Key(_) = event::read()
                    .map_err(|e| ErrorWrapper::validation_failed(format!("Read failed: {}", e)))?
                {
                    break;
                }
            }
        }

        // Execute each field in fragment
        let mut results: Arc<HashMap<String, Value>> = Arc::new(HashMap::new());
        for element in &fragment_form.elements {
            if let crate::form_parser::FormElement::Field(field_def) = element {
                let context = RenderContext {
                    results: Arc::clone(&results),
                    locale: None,
                };
                let value = self.execute_field(field_def, &context).await?;
                Arc::make_mut(&mut results).insert(field_def.name.clone(), value);
            }
        }

        Ok(Arc::try_unwrap(results).unwrap_or_else(|arc| (*arc).clone()))
    }

    /// Summarize an item for display in TUI lists
    fn summarize_item_tui(item: &HashMap<String, Value>) -> String {
        if let Some(first_string) = item.values().find_map(|v| v.as_str()) {
            first_string.chars().take(30).collect()
        } else if let Some(first_value) = item.values().next() {
            format!("{:?}", first_value).chars().take(30).collect()
        } else {
            "(empty)".to_string()
        }
    }

    /// Format a value for preview display
    fn format_value_preview(value: &Value) -> String {
        match value {
            Value::String(s) => s.clone(),
            Value::Number(n) => n.to_string(),
            Value::Bool(b) => b.to_string(),
            Value::Array(arr) => format!("[{} items]", arr.len()),
            Value::Object(_) => "{object}".to_string(),
            Value::Null => "null".to_string(),
        }
    }

    /// Check if a new item is a duplicate of existing items
    fn is_duplicate(
        new_item: &HashMap<String, Value>,
        items: &[HashMap<String, Value>],
        exclude_index: Option<usize>,
    ) -> bool {
        for (idx, existing_item) in items.iter().enumerate() {
            // Skip comparing with self when editing
            if let Some(exclude_idx) = exclude_index {
                if idx == exclude_idx {
                    continue;
                }
            }

            // Check if ALL fields match
            let all_match = new_item
                .iter()
                .all(|(key, value)| existing_item.get(key) == Some(value));

            if all_match && !new_item.is_empty() {
                return true;
            }
        }

        false
    }

    /// Display validation error overlay
    async fn show_validation_error(&self, message: &str) -> Result<()> {
        let mut terminal_ref = self.terminal.write().unwrap();
        if let Some(terminal) = terminal_ref.as_mut() {
            let error_msg = message.to_string();
            terminal
                .draw(|frame| {
                    let area = frame.area();
                    let error_text = format!("Error: {}", error_msg);
                    let paragraph =
                        Paragraph::new(error_text).block(Block::default().borders(Borders::ALL));

                    frame.render_widget(paragraph, area);
                })
                .map_err(|e| {
                    ErrorWrapper::validation_failed(format!("Failed to render error: {}", e))
                })?;

            // Wait for any key press
            loop {
                if event::poll(Duration::from_millis(100))
                    .map_err(|e| ErrorWrapper::validation_failed(format!("Poll failed: {}", e)))?
                {
                    if let Event::Key(_) = event::read().map_err(|e| {
                        ErrorWrapper::validation_failed(format!("Read failed: {}", e))
                    })? {
                        break;
                    }
                }
            }
        }
        Ok(())
    }

    /// Execute editor field with external $EDITOR support
    /// Temporarily exits alternate screen to spawn editor, then returns content
    async fn execute_editor_field(&self, field: &FieldDefinition) -> Result<Value> {
        use std::fs;
        use std::process::Command;
        use std::time::{SystemTime, UNIX_EPOCH};

        loop {
            // Disable raw mode and exit alternate screen temporarily
            disable_raw_mode().map_err(|e| {
                ErrorWrapper::validation_failed(format!("Failed to disable raw mode: {}", e))
            })?;
            execute!(
                io::stdout(),
                LeaveAlternateScreen,
                event::DisableMouseCapture
            )
            .map_err(|e| {
                ErrorWrapper::validation_failed(format!("Failed to exit alternate screen: {}", e))
            })?;

            // Create temporary file with timestamp-based name
            let file_ext = field.file_extension.as_deref().unwrap_or("txt");
            let timestamp = SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap_or_default()
                .as_nanos();
            let temp_file = format!("/tmp/typedialog-{}.{}", timestamp, file_ext);

            // Write prefix text if present
            if let Some(prefix) = &field.prefix_text {
                fs::write(&temp_file, prefix).map_err(|e| {
                    ErrorWrapper::validation_failed(format!("Failed to write temp file: {}", e))
                })?;
            } else {
                fs::write(&temp_file, "").map_err(|e| {
                    ErrorWrapper::validation_failed(format!("Failed to create temp file: {}", e))
                })?;
            }

            // Determine editor command
            let editor = std::env::var("EDITOR").unwrap_or_else(|_| "nano".to_string());

            // Launch editor
            let status = Command::new(&editor)
                .arg(&temp_file)
                .status()
                .map_err(|e| {
                    ErrorWrapper::validation_failed(format!("Failed to launch editor: {}", e))
                })?;

            if !status.success() {
                drop(fs::remove_file(&temp_file));
                // Re-enable terminal
                drop(enable_raw_mode());
                drop(execute!(
                    io::stdout(),
                    EnterAlternateScreen,
                    event::EnableMouseCapture
                ));
                return Err(ErrorWrapper::cancelled_no_context());
            }

            // Read content from temp file
            let content = fs::read_to_string(&temp_file).map_err(|e| {
                ErrorWrapper::validation_failed(format!("Failed to read temp file: {}", e))
            })?;

            // Clean up
            drop(fs::remove_file(&temp_file));

            // Re-enable raw mode and alternate screen
            enable_raw_mode().map_err(|e| {
                ErrorWrapper::validation_failed(format!("Failed to enable raw mode: {}", e))
            })?;
            execute!(
                io::stdout(),
                EnterAlternateScreen,
                event::EnableMouseCapture
            )
            .map_err(|e| {
                ErrorWrapper::validation_failed(format!("Failed to enter alternate screen: {}", e))
            })?;

            // Validate required field
            if field.required.unwrap_or(false) && content.trim().is_empty() {
                self.show_validation_error("Content cannot be empty")
                    .await?;
                continue;
            }

            return Ok(json!(content));
        }
    }

    /// Execute date picker field with spinner-based date selection
    /// Navigate with Tab/Shift+Tab between fields, Up/Down to adjust values
    async fn execute_date_field(&self, field: &FieldDefinition) -> Result<Value> {
        // Parse default or current date
        let default_date = field.default.as_deref().unwrap_or("2024-01-01");
        let (year, month, day) = parse_iso_date(default_date)?;

        let mut state = DatePickerState {
            year,
            month,
            day,
            cursor: DateCursor::Year,
            min_date: field.min_date.as_deref(),
            max_date: field.max_date.as_deref(),
        };

        loop {
            // Render current state
            {
                let mut terminal_ref = self.terminal.write().unwrap();
                if let Some(terminal) = terminal_ref.as_mut() {
                    let prompt = field.prompt.clone();
                    let calendar_view = render_calendar(state.year, state.month, state.day);
                    let year_cursor = if state.cursor == DateCursor::Year {
                        "▶ "
                    } else {
                        "  "
                    };
                    let month_cursor = if state.cursor == DateCursor::Month {
                        "▶ "
                    } else {
                        "  "
                    };
                    let day_cursor = if state.cursor == DateCursor::Day {
                        "▶ "
                    } else {
                        "  "
                    };

                    terminal.draw(|frame| {
                        let area = frame.area();
                        let display_text = format!(
                            "{}:\n{}Year: {}  {}Month: {}  {}Day: {}\n\nInstructions: Tab=field, Up/Down=change, Enter=confirm, Esc=cancel",
                            prompt,
                            year_cursor,
                            state.year,
                            month_cursor,
                            state.month,
                            day_cursor,
                            state.day
                        );

                        let full_text = format!("{}\n{}", calendar_view, display_text);

                        let paragraph = Paragraph::new(full_text)
                            .block(Block::default().borders(Borders::ALL));

                        frame.render_widget(paragraph, area);
                    })
                    .map_err(|e| ErrorWrapper::validation_failed(format!("Failed to render: {}", e)))?;
                } else {
                    return Err(ErrorWrapper::validation_failed("Terminal not initialized"));
                }
            }

            // Event loop
            if event::poll(Duration::from_millis(100))
                .map_err(|e| ErrorWrapper::validation_failed(format!("Poll failed: {}", e)))?
            {
                if let Event::Key(key) = event::read()
                    .map_err(|e| ErrorWrapper::validation_failed(format!("Read failed: {}", e)))?
                {
                    match key.code {
                        KeyCode::Tab => {
                            state.cursor = state.cursor.next();
                        }
                        KeyCode::BackTab => {
                            state.cursor = state.cursor.prev();
                        }
                        KeyCode::Up => match state.cursor {
                            DateCursor::Year => state.year = (state.year + 1).min(2100),
                            DateCursor::Month => {
                                state.month = if state.month == 12 {
                                    1
                                } else {
                                    state.month + 1
                                }
                            }
                            DateCursor::Day => state.day = (state.day + 1).min(31),
                        },
                        KeyCode::Down => match state.cursor {
                            DateCursor::Year => state.year = (state.year - 1).max(1900),
                            DateCursor::Month => {
                                state.month = if state.month == 1 {
                                    12
                                } else {
                                    state.month - 1
                                }
                            }
                            DateCursor::Day => state.day = (state.day - 1).max(1),
                        },
                        KeyCode::Enter => {
                            // Validate date
                            let date_str =
                                format!("{:04}-{:02}-{:02}", state.year, state.month, state.day);
                            if let Err(e) = validate_date(&date_str, state.min_date, state.max_date)
                            {
                                self.show_validation_error(&e).await?;
                                continue;
                            }
                            return Ok(json!(date_str));
                        }
                        KeyCode::Esc => return Err(ErrorWrapper::cancelled_no_context()),
                        _ => {}
                    }
                }
            }
        }
    }
}

/// Render 3-panel form layout: left (fields), center (input), bottom (buttons)
fn render_form_layout(
    frame: &mut ratatui::Frame<'_>,
    fields: &[FieldDefinition],
    results: &std::collections::HashMap<String, Value>,
    selected_index: usize,
    focus_panel: FormPanel,
    button_focus: ButtonFocus,
    field_buffer: &str,
) {
    use ratatui::layout::{Constraint, Direction, Layout};

    if selected_index >= fields.len() {
        return;
    }

    let area = frame.area();

    // Main layout: 3 rows (top empty, middle content, bottom buttons)
    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([Constraint::Min(1), Constraint::Length(3)])
        .split(area);

    let content_area = chunks[0];
    let button_area = chunks[1];

    // Content: 2 columns (left list, right input)
    let content_chunks = Layout::default()
        .direction(Direction::Horizontal)
        .constraints([Constraint::Percentage(35), Constraint::Percentage(65)])
        .split(content_area);

    let list_area = content_chunks[0];
    let input_area = content_chunks[1];

    // Left panel: Field list (only visible fields based on conditionals)
    {
        let border_style = if focus_panel == FormPanel::FieldList {
            Style::default()
                .fg(Color::Cyan)
                .add_modifier(Modifier::BOLD)
        } else {
            Style::default()
        };

        let block = Block::default()
            .title("Fields")
            .borders(Borders::ALL)
            .style(border_style);

        let mut lines = Vec::new();
        let visible_indices = get_visible_field_indices(fields, results);

        for &idx in &visible_indices {
            let field = &fields[idx];
            let is_selected = idx == selected_index;
            let prefix = if is_selected { "▶ " } else { "  " };
            let status = if results.contains_key(&field.name) {
                "✓"
            } else {
                " "
            };
            lines.push(format!("{}{} {}", prefix, status, field.prompt));
        }

        let text = lines.join("\n");
        let paragraph = Paragraph::new(text).block(block);
        frame.render_widget(paragraph, list_area);
    }

    // Right panel: Input field with instructions at bottom
    {
        use ratatui::layout::{Constraint, Direction, Layout};

        let border_style = if focus_panel == FormPanel::InputField {
            Style::default()
                .fg(Color::Green)
                .add_modifier(Modifier::BOLD)
        } else {
            Style::default()
        };

        let title_text = fields[selected_index].prompt.clone();
        let block = Block::default()
            .title(title_text)
            .borders(Borders::ALL)
            .style(border_style);

        // Split input area into content and help sections
        let input_chunks = Layout::default()
            .direction(Direction::Vertical)
            .constraints([Constraint::Min(1), Constraint::Length(2)])
            .split(input_area);

        let content_area = input_chunks[0];
        let help_area = input_chunks[1];

        // Build display text based on field type
        let display_text = if fields[selected_index].field_type == FieldType::Select
            || fields[selected_index].field_type == FieldType::MultiSelect
        {
            // For select fields, show options
            let mut lines = vec![];
            lines.push(format!(
                "  Value: {}",
                if field_buffer.is_empty() {
                    "(empty)"
                } else {
                    field_buffer
                }
            ));
            lines.push("".to_string());

            if !fields[selected_index].options.is_empty() {
                let options = &fields[selected_index].options;
                lines.push("  Options:".to_string());
                for opt in options.iter().take(4) {
                    let marker = if field_buffer == opt.value {
                        "▶"
                    } else {
                        " "
                    };
                    lines.push(format!("    {} {}", marker, opt.display_label()));
                }
                if options.len() > 4 {
                    lines.push(format!("    ... and {} more", options.len() - 4));
                }
            }
            lines.join("\n")
        } else if fields[selected_index].field_type == FieldType::Password {
            // For password fields, mask characters
            let display_value = if field_buffer.is_empty() {
                let placeholder = fields[selected_index]
                    .placeholder
                    .as_deref()
                    .unwrap_or("(empty)");
                format!("{}_", placeholder)
            } else {
                format!("{}_{}", "•".repeat(field_buffer.len()), "")
            };
            format!("  {}", display_value)
        } else if fields[selected_index].field_type == FieldType::Confirm {
            // For confirm (boolean) fields, show Yes/No with indicator
            let is_true = field_buffer == "true";
            let yes_indicator = if is_true { "[✓]" } else { "[ ]" };
            let no_indicator = if !is_true { "[✓]" } else { "[ ]" };
            format!("  {} Yes     {} No", yes_indicator, no_indicator)
        } else {
            // For text fields, show input with spacing and margin
            let input_value = if field_buffer.is_empty() {
                let placeholder = fields[selected_index]
                    .placeholder
                    .as_deref()
                    .unwrap_or("(empty)");
                format!("{}_", placeholder)
            } else {
                format!("{}_", field_buffer)
            };
            format!("  {}", input_value)
        };

        // Render content with block
        let content_para = Paragraph::new(display_text).block(block);
        frame.render_widget(content_para, content_area);

        // Render help text at bottom (without block, just plain text)
        let help_lines = [
            "    Enter: Save  |  Esc: Cancel  |  Ctrl+E: Submit  |  Ctrl+Q: Quit",
            " ",
        ];
        let help_text = help_lines.join("\n");
        let help_para = Paragraph::new(help_text).style(Style::default().fg(Color::DarkGray));
        frame.render_widget(help_para, help_area);
    }

    // Bottom: Buttons
    {
        let button_chunks = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
            .split(button_area);

        let cancel_style =
            if focus_panel == FormPanel::Buttons && button_focus == ButtonFocus::Cancel {
                Style::default().fg(Color::White).bg(Color::Red)
            } else if focus_panel == FormPanel::Buttons {
                Style::default().fg(Color::Red)
            } else {
                Style::default()
            };

        let submit_style =
            if focus_panel == FormPanel::Buttons && button_focus == ButtonFocus::Submit {
                Style::default().fg(Color::White).bg(Color::Green)
            } else if focus_panel == FormPanel::Buttons {
                Style::default().fg(Color::Green)
            } else {
                Style::default()
            };

        let cancel_btn = Paragraph::new("[ Cancel ]").style(cancel_style);
        let submit_btn = Paragraph::new("[ Submit ]").style(submit_style);

        frame.render_widget(cancel_btn, button_chunks[0]);
        frame.render_widget(submit_btn, button_chunks[1]);
    }
}

/// Load field buffer with current value or default
fn load_field_buffer(
    buffer: &mut String,
    field: &FieldDefinition,
    results: &std::collections::HashMap<String, Value>,
) {
    buffer.clear();

    // First, try to get the current value from results
    if let Some(value) = results.get(&field.name) {
        match value {
            Value::String(s) => buffer.push_str(s),
            Value::Bool(b) => buffer.push_str(if *b { "true" } else { "false" }),
            Value::Number(n) => buffer.push_str(&n.to_string()),
            _ => {}
        }
    } else if let Some(default) = &field.default {
        // Use default if no current value
        buffer.push_str(default);
    } else if field.field_type == FieldType::Confirm {
        // For Confirm fields, default to "false" if no explicit default
        buffer.push_str("false");
    } else if (field.field_type == FieldType::Select || field.field_type == FieldType::MultiSelect)
        && !field.options.is_empty()
    {
        // For Select/MultiSelect, default to first option if no explicit default
        buffer.push_str(&field.options[0].value);
    }
}

/// Finalize results by ensuring all fields have values (use defaults if not edited)
fn finalize_results(
    results: &mut std::collections::HashMap<String, Value>,
    fields: &[FieldDefinition],
) {
    for field in fields {
        // Skip if field already has a value
        if results.contains_key(&field.name) {
            continue;
        }

        // Add default or sensible value
        if let Some(default) = &field.default {
            match field.field_type {
                FieldType::Confirm => {
                    let bool_val = default.to_lowercase() == "true";
                    results.insert(field.name.clone(), Value::Bool(bool_val));
                }
                _ => {
                    results.insert(field.name.clone(), Value::String(default.clone()));
                }
            }
        } else {
            // No default, use field type sensible default
            match field.field_type {
                FieldType::Confirm => {
                    results.insert(field.name.clone(), Value::Bool(false));
                }
                FieldType::Select | FieldType::MultiSelect => {
                    if !field.options.is_empty() {
                        results.insert(
                            field.name.clone(),
                            Value::String(field.options[0].value.clone()),
                        );
                    } else {
                        results.insert(field.name.clone(), Value::String(String::new()));
                    }
                }
                _ => {
                    results.insert(field.name.clone(), Value::String(String::new()));
                }
            }
        }
    }
}

/// Check if a field should be visible based on its conditional
fn is_field_visible(
    field: &FieldDefinition,
    results: &std::collections::HashMap<String, Value>,
) -> bool {
    if let Some(condition) = &field.when {
        crate::form_parser::evaluate_condition(condition, results)
    } else {
        true // No condition means always visible
    }
}

/// Get list of visible field indices based on conditionals
fn get_visible_field_indices(
    fields: &[FieldDefinition],
    results: &std::collections::HashMap<String, Value>,
) -> Vec<usize> {
    fields
        .iter()
        .enumerate()
        .filter(|(_, field)| is_field_visible(field, results))
        .map(|(idx, _)| idx)
        .collect()
}

/// Text input widget state (R-STATE-SEPARATION: pure data, no rendering logic)
struct TextInputState {
    buffer: String,
    cursor_pos: usize,
}

/// Confirm widget state
struct ConfirmState {
    value: bool,
}

/// Password input widget state
struct PasswordInputState {
    buffer: String,
    visible: bool,
    with_toggle: bool,
}

/// Select widget state with pagination
struct SelectState {
    options: Vec<String>,
    selected_index: usize,
    scroll_offset: usize,
    page_size: usize,
    vim_mode: bool,
}

/// MultiSelect widget state with checkboxes
struct MultiSelectState {
    options: Vec<String>,
    selected: Vec<bool>,
    cursor_index: usize,
    scroll_offset: usize,
    page_size: usize,
    vim_mode: bool,
}

/// Date picker widget state with cursor navigation
#[derive(Clone, Copy, PartialEq)]
struct DatePickerState<'a> {
    year: i32,
    month: u32,
    day: u32,
    cursor: DateCursor,
    min_date: Option<&'a str>,
    max_date: Option<&'a str>,
}

/// Date cursor position (Year, Month, or Day)
#[derive(Clone, Copy, PartialEq, Debug)]
enum DateCursor {
    Year,
    Month,
    Day,
}

impl DateCursor {
    fn next(self) -> Self {
        match self {
            DateCursor::Year => DateCursor::Month,
            DateCursor::Month => DateCursor::Day,
            DateCursor::Day => DateCursor::Year,
        }
    }

    fn prev(self) -> Self {
        match self {
            DateCursor::Year => DateCursor::Day,
            DateCursor::Month => DateCursor::Year,
            DateCursor::Day => DateCursor::Month,
        }
    }
}

/// Helper to evaluate conditional display logic
fn evaluate_condition(
    _condition: &str,
    _results: &std::collections::HashMap<String, Value>,
) -> bool {
    // Simple condition evaluation - placeholder for now
    // Full implementation would parse conditions like "field == value"
    true
}

/// Validate custom type field input
fn validate_custom_type(input: &str, type_name: &str) -> Result<()> {
    match type_name {
        "i32" => {
            input
                .parse::<i32>()
                .map_err(|_| ErrorWrapper::validation_failed("Expected a 32-bit integer"))?;
            Ok(())
        }
        "i64" => {
            input
                .parse::<i64>()
                .map_err(|_| ErrorWrapper::validation_failed("Expected a 64-bit integer"))?;
            Ok(())
        }
        "u32" => {
            input.parse::<u32>().map_err(|_| {
                ErrorWrapper::validation_failed("Expected an unsigned 32-bit integer")
            })?;
            Ok(())
        }
        "u64" => {
            input.parse::<u64>().map_err(|_| {
                ErrorWrapper::validation_failed("Expected an unsigned 64-bit integer")
            })?;
            Ok(())
        }
        "f32" => {
            input
                .parse::<f32>()
                .map_err(|_| ErrorWrapper::validation_failed("Expected a 32-bit floating point"))?;
            Ok(())
        }
        "f64" => {
            input
                .parse::<f64>()
                .map_err(|_| ErrorWrapper::validation_failed("Expected a 64-bit floating point"))?;
            Ok(())
        }
        "ipv4" => {
            input.parse::<std::net::Ipv4Addr>().map_err(|_| {
                ErrorWrapper::validation_failed("Expected valid IPv4 address (e.g., 192.168.1.1)")
            })?;
            Ok(())
        }
        "ipv6" => {
            input
                .parse::<std::net::Ipv6Addr>()
                .map_err(|_| ErrorWrapper::validation_failed("Expected valid IPv6 address"))?;
            Ok(())
        }
        "uuid" => {
            // Simple check for UUID format (no external crate dependency)
            if input.len() == 36 && input.matches('-').count() == 4 {
                Ok(())
            } else {
                Err(ErrorWrapper::validation_failed(
                    "Expected UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
                ))
            }
        }
        "String" | "str" => Ok(()),
        "bool" => match input.to_lowercase().as_str() {
            "true" | "false" | "yes" | "no" | "y" | "n" | "1" | "0" => Ok(()),
            _ => Err(ErrorWrapper::validation_failed(
                "Expected: true, false, yes, no, y, n, 1, or 0",
            )),
        },
        _ => Ok(()), // Unknown type, accept as string
    }
}

/// Parse ISO 8601 date string (YYYY-MM-DD) to components
fn parse_iso_date(date_str: &str) -> Result<(i32, u32, u32)> {
    let parts: Vec<&str> = date_str.split('-').collect();
    if parts.len() != 3 {
        return Err(ErrorWrapper::validation_failed(
            "Invalid date format (expected YYYY-MM-DD)",
        ));
    }

    let year = parts[0]
        .parse::<i32>()
        .map_err(|_| ErrorWrapper::validation_failed("Invalid year"))?;
    let month = parts[1]
        .parse::<u32>()
        .map_err(|_| ErrorWrapper::validation_failed("Invalid month"))?;
    let day = parts[2]
        .parse::<u32>()
        .map_err(|_| ErrorWrapper::validation_failed("Invalid day"))?;

    if !(1..=12).contains(&month) {
        return Err(ErrorWrapper::validation_failed("Month must be 1-12"));
    }
    if !(1..=31).contains(&day) {
        return Err(ErrorWrapper::validation_failed("Day must be 1-31"));
    }

    Ok((year, month, day))
}

/// Validate date against min_date and max_date constraints
fn validate_date(
    date_str: &str,
    min_date: Option<&str>,
    max_date: Option<&str>,
) -> std::result::Result<(), String> {
    if let Some(min) = min_date {
        if date_str < min {
            return Err(format!("Date must be on or after {}", min));
        }
    }

    if let Some(max) = max_date {
        if date_str > max {
            return Err(format!("Date must be on or before {}", max));
        }
    }

    Ok(())
}

/// Get the day of the week for the first day of the month (0=Monday, 6=Sunday)
/// Using Zeller's congruence for simplicity
fn first_day_of_month(year: i32, month: u32) -> usize {
    let (adj_month, adj_year) = if month < 3 {
        (month + 12, year - 1)
    } else {
        (month, year)
    };

    let k = adj_year % 100;
    let j = adj_year / 100;
    let adj_month = adj_month as i32;
    let h = (1 + (13 * (adj_month + 1)) / 5 + k + k / 4 + j / 4 - 2 * j) % 7;

    // Convert Saturday=0 to Monday=0
    ((h + 5) % 7).max(0) as usize
}

/// Get number of days in a month
fn days_in_month(year: i32, month: u32) -> u32 {
    match month {
        1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
        4 | 6 | 9 | 11 => 30,
        2 => {
            if (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 {
                29
            } else {
                28
            }
        }
        _ => 30,
    }
}

/// Render calendar as ASCII grid
fn render_calendar(year: i32, month: u32, selected_day: u32) -> String {
    let month_names = [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December",
    ];
    let day_names = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];

    let mut calendar = format!("\n  {} {}\n", month_names[(month - 1) as usize], year);
    calendar.push_str(&format!(
        "  {} {} {} {} {} {} {}\n",
        day_names[0],
        day_names[1],
        day_names[2],
        day_names[3],
        day_names[4],
        day_names[5],
        day_names[6]
    ));

    let first_day = first_day_of_month(year, month);
    let days = days_in_month(year, month);

    // Padding for first week
    for _ in 0..first_day {
        calendar.push_str("    ");
    }

    // Days of month
    for day in 1..=days {
        let day_display = if day == selected_day {
            format!("[{:2}]", day)
        } else {
            format!(" {:2} ", day)
        };
        calendar.push_str(&day_display);

        // New line on Sunday
        if (first_day + (day as usize - 1)) % 7 == 6 {
            calendar.push('\n');
        }
    }

    calendar.push('\n');
    calendar
}

/// Parse and convert custom type field input to appropriate JSON value
fn parse_custom_value(input: &str, type_name: &str) -> Value {
    match type_name {
        "i32" => input
            .parse::<i32>()
            .map(|v| json!(v))
            .unwrap_or_else(|_| json!(input)),
        "i64" => input
            .parse::<i64>()
            .map(|v| json!(v))
            .unwrap_or_else(|_| json!(input)),
        "u32" => input
            .parse::<u32>()
            .map(|v| json!(v))
            .unwrap_or_else(|_| json!(input)),
        "u64" => input
            .parse::<u64>()
            .map(|v| json!(v))
            .unwrap_or_else(|_| json!(input)),
        "f32" => input
            .parse::<f32>()
            .map(|v| json!(v))
            .unwrap_or_else(|_| json!(input)),
        "f64" => input
            .parse::<f64>()
            .map(|v| json!(v))
            .unwrap_or_else(|_| json!(input)),
        "bool" => match input.to_lowercase().as_str() {
            "true" | "yes" | "y" | "1" => json!(true),
            "false" | "no" | "n" | "0" => json!(false),
            _ => json!(input),
        },
        _ => json!(input), // Default to string
    }
}

/// Render complete form UI with all fields visible
/// Shows current field with focus highlighting
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_ratatui_backend_new() {
        let backend = RatatuiBackend::new();
        assert_eq!(backend.name(), "tui");
    }

    #[test]
    fn test_ratatui_backend_default() {
        let backend = RatatuiBackend::default();
        assert_eq!(backend.name(), "tui");
    }

    #[test]
    fn test_terminal_guard_drop() {
        // Verify TerminalGuard can be created and dropped
        let _guard = TerminalGuard;
        // Drop should be called on scope exit without panicking
    }

    #[test]
    fn test_parse_iso_date_valid() {
        let (year, month, day) = parse_iso_date("2024-12-25").unwrap();
        assert_eq!(year, 2024);
        assert_eq!(month, 12);
        assert_eq!(day, 25);
    }

    #[test]
    fn test_parse_iso_date_invalid_format() {
        assert!(parse_iso_date("2024/12/25").is_err());
        assert!(parse_iso_date("12-25-2024").is_err());
    }

    #[test]
    fn test_parse_iso_date_invalid_month() {
        assert!(parse_iso_date("2024-13-25").is_err());
        assert!(parse_iso_date("2024-00-25").is_err());
    }

    #[test]
    fn test_parse_iso_date_invalid_day() {
        assert!(parse_iso_date("2024-12-32").is_err());
        assert!(parse_iso_date("2024-12-00").is_err());
    }

    #[test]
    fn test_validate_date_within_range() {
        assert!(validate_date("2024-06-15", Some("2024-01-01"), Some("2024-12-31")).is_ok());
    }

    #[test]
    fn test_validate_date_before_min() {
        assert!(validate_date("2023-12-31", Some("2024-01-01"), None).is_err());
    }

    #[test]
    fn test_validate_date_after_max() {
        assert!(validate_date("2025-01-01", None, Some("2024-12-31")).is_err());
    }

    #[test]
    fn test_days_in_month_31() {
        assert_eq!(days_in_month(2024, 1), 31); // January
        assert_eq!(days_in_month(2024, 3), 31); // March
        assert_eq!(days_in_month(2024, 5), 31); // May
        assert_eq!(days_in_month(2024, 7), 31); // July
        assert_eq!(days_in_month(2024, 8), 31); // August
        assert_eq!(days_in_month(2024, 10), 31); // October
        assert_eq!(days_in_month(2024, 12), 31); // December
    }

    #[test]
    fn test_days_in_month_30() {
        assert_eq!(days_in_month(2024, 4), 30); // April
        assert_eq!(days_in_month(2024, 6), 30); // June
        assert_eq!(days_in_month(2024, 9), 30); // September
        assert_eq!(days_in_month(2024, 11), 30); // November
    }

    #[test]
    fn test_days_in_month_february_leap() {
        assert_eq!(days_in_month(2024, 2), 29); // 2024 is leap year
        assert_eq!(days_in_month(2023, 2), 28); // 2023 is not leap year
    }

    #[test]
    fn test_validate_custom_type_i32() {
        assert!(validate_custom_type("42", "i32").is_ok());
        assert!(validate_custom_type("-42", "i32").is_ok());
        assert!(validate_custom_type("abc", "i32").is_err());
    }

    #[test]
    fn test_validate_custom_type_f64() {
        assert!(validate_custom_type("3.14", "f64").is_ok());
        assert!(validate_custom_type("-2.5", "f64").is_ok());
        assert!(validate_custom_type("abc", "f64").is_err());
    }

    #[test]
    fn test_validate_custom_type_ipv4() {
        assert!(validate_custom_type("192.168.1.1", "ipv4").is_ok());
        assert!(validate_custom_type("255.255.255.255", "ipv4").is_ok());
        assert!(validate_custom_type("256.1.1.1", "ipv4").is_err());
    }

    #[test]
    fn test_validate_custom_type_bool() {
        assert!(validate_custom_type("true", "bool").is_ok());
        assert!(validate_custom_type("false", "bool").is_ok());
        assert!(validate_custom_type("yes", "bool").is_ok());
        assert!(validate_custom_type("no", "bool").is_ok());
        assert!(validate_custom_type("maybe", "bool").is_err());
    }

    #[test]
    fn test_parse_custom_value_i32() {
        assert_eq!(parse_custom_value("42", "i32"), json!(42));
        assert_eq!(parse_custom_value("abc", "i32"), json!("abc"));
    }

    #[test]
    fn test_parse_custom_value_bool() {
        assert_eq!(parse_custom_value("true", "bool"), json!(true));
        assert_eq!(parse_custom_value("false", "bool"), json!(false));
        assert_eq!(parse_custom_value("yes", "bool"), json!(true));
        assert_eq!(parse_custom_value("no", "bool"), json!(false));
    }

    #[test]
    fn test_date_cursor_navigation() {
        let mut cursor = DateCursor::Year;
        cursor = cursor.next();
        assert_eq!(cursor, DateCursor::Month);
        cursor = cursor.next();
        assert_eq!(cursor, DateCursor::Day);
        cursor = cursor.next();
        assert_eq!(cursor, DateCursor::Year);
    }

    #[test]
    fn test_date_cursor_prev_navigation() {
        let mut cursor = DateCursor::Day;
        cursor = cursor.prev();
        assert_eq!(cursor, DateCursor::Month);
        cursor = cursor.prev();
        assert_eq!(cursor, DateCursor::Year);
        cursor = cursor.prev();
        assert_eq!(cursor, DateCursor::Day);
    }

    #[test]
    fn test_render_calendar_contains_month() {
        let calendar = render_calendar(2024, 12, 25);
        assert!(calendar.contains("December"));
        assert!(calendar.contains("2024"));
    }

    #[test]
    fn test_render_calendar_highlights_selected_day() {
        let calendar = render_calendar(2024, 12, 25);
        assert!(calendar.contains("[25]"));
    }

    #[test]
    fn test_render_calendar_valid_days() {
        let calendar = render_calendar(2024, 2, 15);
        // February 2024 has 29 days (leap year)
        assert!(calendar.contains("29"));
    }

    #[test]
    fn test_first_day_of_month_known_dates() {
        // These are known day-of-week values
        // January 1, 2024 is a Monday (0)
        assert_eq!(first_day_of_month(2024, 1), 0);
    }

    // =========================================================================
    // TUI REACTIVE RENDERING TESTS (FASE 3)
    // =========================================================================

    /// Test that recompute_form_view successfully handles form recomputation
    /// This validates that the reactive re-rendering infrastructure works correctly
    /// by updating visible items and fields based on current results
    #[test]
    fn test_recompute_form_view_reactive_rendering() {
        let mut items: Vec<DisplayItem> = vec![];
        let mut fields: Vec<FieldDefinition> = vec![];
        let results = std::collections::HashMap::new();

        let mut selected_index = 0;
        let mut field_buffer = String::new();

        // Create minimal form for testing
        let form = crate::form_parser::FormDefinition {
            name: "test".to_string(),
            description: None,
            locale: None,
            template: None,
            output_template: None,
            i18n_prefix: None,
            display_mode: crate::form_parser::DisplayMode::Complete,
            items: vec![],
            fields: vec![],
            elements: vec![],
        };

        let temp_dir = std::path::Path::new("/tmp");

        // Test with empty vectors - validates recompute_form_view returns success
        let result = recompute_form_view(
            &form,
            temp_dir,
            &results,
            &mut items,
            &mut fields,
            &mut selected_index,
            &mut field_buffer,
        );
        assert!(
            result.is_ok(),
            "recompute_form_view should handle empty items and fields"
        );

        // Navigation should be reset to 0
        assert_eq!(selected_index, 0);
        // Field buffer should be empty when no fields exist
        assert!(field_buffer.is_empty());
    }
}
