//! UI components and rendering for the TUI - R-WIDGET-COMPOSITION pattern
//!
//! This module implements the R-WIDGET-COMPOSITION design pattern:
//! - Pure rendering functions that only READ application state
//! - No state mutations (functions take `&App`, never `&mut App`)
//! - Widgets are composable and reusable
//! - Rendering logic is separated from business logic
//!
//! # Usage in Event Loop
//!
//! ```no_run
//! use ratatui::prelude::*;
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! # let mut app = todo!();
//! # let mut terminal = todo!();
//! loop {
//!     // Only redraw when dirty flag is set
//!     if app.dirty {
//!         terminal.draw(|f| {
//!             // Call render functions - these are pure, read-only
//!             render(f, &app);
//!         })?;
//!         app.mark_rendered();  // Clear dirty flag after rendering
//!     }
//!
//!     // Handle events
//!     if app.should_quit {
//!         break;
//!     }
//! }
//! # Ok(())
//! # }
//! ```

use crate::app::{App, Screen};
use crate::theme::AppTheme;
use crate::types::ProjectDto;
use crate::{delete_confirm, edit_task, help, theme_selector};
use ratatui::{
    prelude::*,
    widgets::{Block, Borders, List, ListItem, Paragraph, Wrap},
};
use tools_tui_shared::prelude::{AppFooter, AppHeader, Theme};

// ============================================================================
// MAIN RENDER FUNCTION - R-WIDGET-COMPOSITION
// ============================================================================

/// Main render function - coordinates all UI rendering
///
/// # R-WIDGET-COMPOSITION Pattern
///
/// This function:
/// - Takes `&App` (read-only, immutable state)
/// - Never modifies state
/// - Routes to appropriate screen renderer based on current state
/// - Composes widgets together
///
/// # Example
///
/// ```no_run
/// terminal.draw(|f| {
///     render(f, &app);
/// })?;
/// ```
pub(crate) fn render(f: &mut Frame<'_>, app: &App) {
    let size = f.area();

    // Get theme based on app settings
    let base_theme = match app.current_theme.as_str() {
        "dark" => Theme::dark(),
        "light" => Theme::light(),
        "minimal" => Theme::minimal(),
        "professional" => Theme::professional(),
        _ => Theme::default(),
    };

    let app_theme = AppTheme::new(base_theme);

    // Main layout: header + content + footer
    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(3), // Header
            Constraint::Min(5),    // Content area
            Constraint::Length(2), // Footer
        ])
        .split(size);

    // Render header with theme
    render_app_header(f, chunks[0], &app_theme.base);

    // Render current screen based on state with app theme
    match app.screen {
        Screen::ProjectsList => render_projects_screen(f, chunks[1], app, &app_theme),
        Screen::ProjectDetail => render_project_detail_screen(f, chunks[1], app, &app_theme),
        Screen::Security => render_security_screen(f, chunks[1], app, &app_theme),
        Screen::CreateProject => render_create_project_screen(f, chunks[1], app, &app_theme),
        Screen::Tasks => render_tasks_screen(f, chunks[1], app, &app_theme),
        Screen::CreateTask => render_create_task_screen(f, chunks[1], app, &app_theme),
        Screen::EditTask => edit_task::render_edit_task_screen(f, app, chunks[1], &app_theme),
        Screen::TasksFilter => render_filter_screen(f, chunks[1], app, &app_theme),
        Screen::DeleteConfirm => {
            // Render tasks screen in background, then overlay modal
            render_tasks_screen(f, chunks[1], app, &app_theme);
            delete_confirm::render_delete_confirm_modal(f, app, size, &app_theme);
        }
        Screen::Help => help::render_help_screen(f, app, size, &app_theme),
        Screen::ThemeSelector => theme_selector::render_theme_selector(f, app, size, &app_theme),
    }

    // Render footer with theme
    render_app_footer(f, chunks[2], app, &app_theme.base);
}

// ============================================================================
// SCREEN RENDERERS - R-WIDGET-COMPOSITION
// ============================================================================

/// Render projects list screen
fn render_projects_screen(f: &mut Frame<'_>, area: Rect, app: &App, theme: &AppTheme) {
    let _ = theme; // Use theme for styling if needed
                   // Split area into sidebar and main content
    let chunks = Layout::default()
        .direction(Direction::Horizontal)
        .constraints([
            Constraint::Percentage(50), // Projects list
            Constraint::Percentage(50), // Metrics/info
        ])
        .split(area);

    // Left: Projects list
    render_projects_list(f, chunks[0], app);

    // Right: Loading/Error/Info
    if app.is_loading {
        render_loading(f, chunks[1]);
    } else if let Some(error) = &app.error {
        render_error(f, chunks[1], error);
    } else {
        render_projects_info(f, chunks[1], app);
    }
}

/// Render project detail screen
fn render_project_detail_screen(f: &mut Frame<'_>, area: Rect, app: &App, theme: &AppTheme) {
    let _ = theme; // Use theme for styling if needed
    if let Some(project) = &app.current_project {
        if app.is_loading {
            render_loading(f, area);
        } else {
            render_project_detail(f, area, project);
        }
    } else {
        render_error(f, area, "No project selected");
    }
}

/// Render security assessment screen
fn render_security_screen(f: &mut Frame<'_>, area: Rect, _app: &App, theme: &AppTheme) {
    let _ = theme; // Use theme for styling if needed
    let content = "Security Assessment Screen\n\nFeatures coming soon...";
    let widget = Paragraph::new(content)
        .block(Block::default().borders(Borders::ALL).title(" Security "))
        .style(Style::default().fg(Color::Blue));

    f.render_widget(widget, area);
}

/// Render create project screen
fn render_create_project_screen(f: &mut Frame<'_>, area: Rect, app: &App, theme: &AppTheme) {
    let _ = theme; // Use theme for styling if needed
    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(4),
            Constraint::Length(4),
            Constraint::Min(2),
        ])
        .split(area);

    // Name input
    let name_widget = Paragraph::new(format!("Name: {}", app.project_name_input)).block(
        Block::default()
            .borders(Borders::ALL)
            .title(" Project Name "),
    );
    f.render_widget(name_widget, chunks[0]);

    // Description input
    let desc_widget = Paragraph::new(format!("Description: {}", app.project_desc_input)).block(
        Block::default()
            .borders(Borders::ALL)
            .title(" Description "),
    );
    f.render_widget(desc_widget, chunks[1]);

    // Instructions
    let help_text = "Enter name and description, press Enter to create (Esc to cancel)";
    let help = Paragraph::new(help_text)
        .style(Style::default().fg(Color::DarkGray))
        .alignment(Alignment::Left);
    f.render_widget(help, chunks[2]);
}

/// Render tasks/checklist screen
fn render_tasks_screen(f: &mut Frame<'_>, area: Rect, app: &App, theme: &AppTheme) {
    let _ = theme; // Use theme for styling if needed

    if app.is_loading {
        render_loading(f, area);
        return;
    }

    if let Some(error) = &app.error {
        render_error(f, area, error);
        return;
    }

    // Split area: statistics on top, then tasks list and details below
    let top_chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(6), // Statistics section
            Constraint::Min(0),    // Rest for tasks
        ])
        .split(area);

    // Top: Statistics
    render_statistics(f, top_chunks[0], app);

    // Split bottom area into tasks list and task details
    let chunks = Layout::default()
        .direction(Direction::Horizontal)
        .constraints([
            Constraint::Percentage(50), // Tasks list
            Constraint::Percentage(50), // Task details
        ])
        .split(top_chunks[1]);

    // Left: Tasks list
    render_tasks_list(f, chunks[0], app);

    // Right: Task details/stats
    render_task_details(f, chunks[1], app);
}

/// Render task statistics (total, completed, pending, percentage)
fn render_statistics(f: &mut Frame<'_>, area: Rect, app: &App) {
    let (total, completed, pending, percentage) = app.calculate_statistics();

    // Create progress bar: filled for completed, empty for pending
    let progress_width = area.width.saturating_sub(2) as usize; // Account for borders
    let filled = ((percentage / 100.0) * progress_width as f64).floor() as usize;
    let empty = progress_width.saturating_sub(filled);
    let progress_bar = format!("[{}{}]", "█".repeat(filled), "░".repeat(empty));

    // Add delete confirmation hint for inline mode
    let delete_hint = if matches!(app.delete_confirmation_mode, crate::app::DeleteMode::Inline)
        && app.delete_confirm_pending
    {
        " | Press 'd' again to confirm deletion"
    } else if matches!(app.delete_confirmation_mode, crate::app::DeleteMode::Prompt)
        && app.awaiting_delete_confirm
    {
        " | Delete? (y/n)"
    } else {
        ""
    };

    let stats_text = format!(
        "Total: {} | Completed: {} ✓ | Pending: {} ⏳ | Progress: {:.1}%{}\n\n{}",
        total, completed, pending, percentage, delete_hint, progress_bar
    );

    let widget = Paragraph::new(stats_text)
        .block(Block::default().borders(Borders::ALL).title(" Statistics "))
        .style(Style::default().fg(Color::Cyan))
        .alignment(Alignment::Left);

    f.render_widget(widget, area);
}

/// Render tasks list with selection
/// # R-LIST-STATE Pattern
/// Uses ListState for efficient task list rendering
/// Uses filtered_tasks() to apply search and filter logic
fn render_tasks_list(f: &mut Frame<'_>, area: Rect, app: &App) {
    let filtered = app.filtered_tasks();

    let items: Vec<ListItem<'_>> = filtered
        .iter()
        .map(|task| {
            let status = if task.completed { "✓" } else { " " };
            let content = format!("[{}] {}", status, task.description);
            ListItem::new(content).style(Style::default())
        })
        .collect();

    // Add filter indicator to title
    let title = if app.task_search_query.is_empty() && app.task_filter_completed.is_none() {
        format!(" Tasks ({}) ", filtered.len())
    } else {
        format!(" Tasks ({}) [Filtered] ", filtered.len())
    };

    let mut list = List::new(items)
        .block(Block::default().borders(Borders::ALL).title(title))
        .style(Style::default());

    if !filtered.is_empty() {
        list = list.highlight_style(Style::default().fg(Color::Green).bg(Color::DarkGray).bold());
    }

    // Use ListState from app state for consistency
    let mut state = app.tasks_list_state;
    f.render_stateful_widget(list, area, &mut state);
}

/// Render task details panel
fn render_task_details(f: &mut Frame<'_>, area: Rect, app: &App) {
    let filtered = app.filtered_tasks();

    if filtered.is_empty() {
        let msg = if app.tasks.is_empty() {
            "No tasks available".to_string()
        } else {
            "No tasks match filter".to_string()
        };
        let widget = Paragraph::new(msg)
            .block(Block::default().borders(Borders::ALL).title(" Details "))
            .style(Style::default().fg(Color::DarkGray))
            .alignment(Alignment::Center);
        f.render_widget(widget, area);
        return;
    }

    // Get selected task from ListState (using filtered list)
    if let Some(selected) = app.tasks_list_state.selected() {
        if let Some(task) = filtered.get(selected) {
            let status = if task.completed {
                "✓ Done"
            } else {
                "○ Pending"
            };
            let content = format!(
                "Task ID: {}\nStatus: {}\nDescription: {}\nCreated: {}\nCompleted: {}",
                task.task_id,
                status,
                task.description,
                task.created_at,
                task.completed_at.as_deref().unwrap_or("Not completed"),
            );

            let widget = Paragraph::new(content)
                .block(
                    Block::default()
                        .borders(Borders::ALL)
                        .title(" Task Details "),
                )
                .style(Style::default().fg(Color::White))
                .wrap(Wrap { trim: true });

            f.render_widget(widget, area);
        }
    }
}

/// Render task creation/editing screen
/// # R-TEXTAREA-BASIC Pattern
/// Uses tui-textarea for multi-line task description input
fn render_create_task_screen(f: &mut Frame<'_>, area: Rect, app: &App, _theme: &AppTheme) {
    // Split area: form title + textarea + validation message
    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(1), // Title
            Constraint::Min(6),    // Textarea area
            Constraint::Length(2), // Error/help message
        ])
        .split(area);

    // Render title
    let title = Paragraph::new("Create New Task (Ctrl+Enter to save, Esc to cancel)")
        .style(Style::default().fg(Color::Cyan).bold());
    f.render_widget(title, chunks[0]);

    // Render textarea content as paragraph with border
    // tui-textarea doesn't implement Widget, so we render its content directly
    let textarea_content = app.task_textarea.lines().join("\n");
    let textarea_widget = Paragraph::new(textarea_content)
        .block(
            Block::default()
                .borders(Borders::ALL)
                .title(" Task Description ")
                .border_type(ratatui::widgets::BorderType::Rounded),
        )
        .style(Style::default().fg(Color::White))
        .wrap(Wrap { trim: false });

    f.render_widget(textarea_widget, chunks[1]);

    // Render validation message or help text
    if let Some(error) = &app.task_form_error {
        let help_widget =
            Paragraph::new(error.as_str()).style(Style::default().fg(Color::Red).bold());
        f.render_widget(help_widget, chunks[2]);
    } else {
        let char_count = app.task_textarea.lines().join("\n").len();
        let help = format!(
            "Characters: {}/500 | Ctrl+Enter: Save | Esc: Cancel",
            char_count
        );
        let help_widget = Paragraph::new(help).style(Style::default().fg(Color::Gray).italic());
        f.render_widget(help_widget, chunks[2]);
    }
}

/// Render task filter and sort screen
fn render_filter_screen(f: &mut Frame<'_>, area: Rect, app: &App, _theme: &AppTheme) {
    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(2), // Title
            Constraint::Length(2), // Status
            Constraint::Length(2), // Search box
            Constraint::Length(1), // Separator
            Constraint::Min(8),    // Sort options
            Constraint::Length(3), // Help
        ])
        .split(area);

    // Render title
    let title = Paragraph::new("Filter & Sort Tasks")
        .style(Style::default().fg(Color::Cyan).bold())
        .alignment(Alignment::Left);
    f.render_widget(title, chunks[0]);

    // Render filter status
    let filter_status = format!(
        "Filter: {} | Sort: {}",
        match app.task_filter_completed {
            None => "All Tasks",
            Some(true) => "Completed Only",
            Some(false) => "Pending Only",
        },
        app.task_sort.label()
    );
    let status_widget = Paragraph::new(filter_status).style(Style::default().fg(Color::Yellow));
    f.render_widget(status_widget, chunks[1]);

    // Render search box
    let search_box = Paragraph::new(format!("Search: {}_", app.task_search_query))
        .block(
            Block::default()
                .borders(Borders::ALL)
                .border_type(ratatui::widgets::BorderType::Rounded),
        )
        .style(Style::default().fg(Color::Cyan));
    f.render_widget(search_box, chunks[2]);

    // Render separator
    f.render_widget(Paragraph::new("─".repeat(area.width as usize)), chunks[3]);

    // Render sort options
    let sort_options: Vec<ListItem<'_>> = crate::app::TaskSortOption::all()
        .iter()
        .enumerate()
        .map(|(idx, opt)| {
            let prefix = if idx == app.filter_sort_selected {
                "→ "
            } else {
                "  "
            };
            let style = if idx == app.filter_sort_selected {
                Style::default().fg(Color::Green).bold()
            } else {
                Style::default().fg(Color::Gray)
            };
            ListItem::new(format!("{}{}", prefix, opt.label())).style(style)
        })
        .collect();

    let sort_list = List::new(sort_options)
        .block(
            Block::default()
                .borders(Borders::ALL)
                .title(" Sort Order ")
                .border_type(ratatui::widgets::BorderType::Rounded),
        )
        .style(Style::default().fg(Color::White));
    f.render_widget(sort_list, chunks[4]);

    // Render help text
    let help_lines = [
        "Type to search | ↑/k: Previous  ↓/j: Next  Enter: Apply",
        "f: Toggle Filter (All/Completed/Pending)  c: Clear All",
        "b/Esc: Back to Tasks",
    ];
    let help_widget =
        Paragraph::new(help_lines.join("\n")).style(Style::default().fg(Color::DarkGray).italic());
    f.render_widget(help_widget, chunks[5]);
}

// ============================================================================
// COMPONENT RENDERERS - R-WIDGET-COMPOSITION
// ============================================================================

/// Render application header
fn render_app_header(f: &mut Frame<'_>, area: Rect, theme: &Theme) {
    let header = AppHeader::new("📋 Lifecycle Manager");
    header.render(f, area, theme);
}

/// Render application footer with help text
fn render_app_footer(f: &mut Frame<'_>, area: Rect, app: &App, theme: &Theme) {
    let help_text = if app.is_loading {
        "Loading...".to_string()
    } else if app.error.is_some() {
        "Error occurred (q to quit)".to_string()
    } else {
        match app.screen {
            Screen::ProjectsList => {
                "q: Quit | ↑↓: Navigate | Enter: Select | c: Create | s: Security".to_string()
            }
            Screen::ProjectDetail => {
                "q/Esc: Back | Space: Details | t: Tasks | s: Security".to_string()
            }
            Screen::Security => "q/Esc: Back".to_string(),
            Screen::CreateProject => "Enter: Create | Esc: Cancel".to_string(),
            Screen::Tasks => {
                "q/Esc: Back | ↑↓: Navigate | Space: Toggle | n: New | e: Edit | d: Delete | ?: Help | T: Themes".to_string()
            }
            Screen::CreateTask => "Ctrl+Enter: Create | Esc: Cancel".to_string(),
            Screen::EditTask => "Ctrl+Enter: Save | Esc: Cancel".to_string(),
            Screen::TasksFilter => {
                "↑↓: Navigate | f: Toggle Filter | c: Clear | Enter: Apply | Esc: Back".to_string()
            }
            Screen::DeleteConfirm => "y/Enter: Confirm | n/Esc: Cancel".to_string(),
            Screen::Help => "↑↓: Scroll | Esc/q: Close".to_string(),
            Screen::ThemeSelector => "↑↓: Navigate | Enter: Apply | Esc: Cancel".to_string(),
        }
    };

    let footer = AppFooter::new(help_text);
    footer.render(f, area, theme);
}

/// Render projects list with selection
/// # R-LIST-STATE Pattern
/// Uses ListState for efficient list rendering and selection
fn render_projects_list(f: &mut Frame<'_>, area: Rect, app: &App) {
    let items: Vec<ListItem<'_>> = app // ListItem needs explicit lifetime parameter
        .projects
        .iter()
        .map(|p| {
            let content = format!("{} [{}] - {}", p.name, p.current_phase, p.version);
            ListItem::new(content).style(Style::default())
        })
        .collect();

    let mut list = List::new(items)
        .block(Block::default().borders(Borders::ALL).title(" Projects "))
        .style(Style::default());

    if !app.projects.is_empty() {
        list = list.highlight_style(
            Style::default()
                .fg(Color::Yellow)
                .bg(Color::DarkGray)
                .bold(),
        );
    }

    // Use ListState from app state for consistency
    let mut state = app.projects_list_state;
    f.render_stateful_widget(list, area, &mut state);
}

/// Render projects info panel
fn render_projects_info(f: &mut Frame<'_>, area: Rect, app: &App) {
    let selected_name = if let Some(selected) = app.projects_list_state.selected() {
        app.projects
            .get(selected)
            .map(|p| p.name.as_str())
            .unwrap_or("None")
    } else {
        "None"
    };

    let content = format!(
        "Total Projects: {}\nSelected: {}\n\nPress Enter to view details",
        app.projects.len(),
        selected_name
    );

    let widget = Paragraph::new(content)
        .block(Block::default().borders(Borders::ALL).title(" Info "))
        .style(Style::default().fg(Color::White));

    f.render_widget(widget, area);
}

// ============================================================================
// LEGACY/DEPRECATED FUNCTIONS (kept for backward compatibility)
// ============================================================================

/// Render project details
///
/// # Deprecation Notice
/// Use the new `render_project_detail_screen()` function which follows
/// R-WIDGET-COMPOSITION pattern
pub(crate) fn render_project_detail(f: &mut Frame<'_>, area: Rect, project: &ProjectDto) {
    let content = format!(
        "ID: {}\nName: {}\nVersion: {}\nType: {}\nPhase: {}\nDescription: {}\nCreated: {}",
        project.id,
        project.name,
        project.version,
        project.project_type,
        project.current_phase,
        project.description,
        project.created_at
    );

    let paragraph = Paragraph::new(content)
        .block(Block::default().borders(Borders::ALL).title(" Details "))
        .wrap(Wrap { trim: true });

    f.render_widget(paragraph, area);
}

/// Render a loading message
pub(crate) fn render_loading(f: &mut Frame<'_>, area: Rect) {
    let loading = Paragraph::new("Loading...")
        .style(Style::default().fg(Color::Yellow))
        .alignment(Alignment::Center);

    f.render_widget(loading, area);
}

/// Render an error message
pub(crate) fn render_error(f: &mut Frame<'_>, area: Rect, error: &str) {
    let error_widget = Paragraph::new(error)
        .block(Block::default().borders(Borders::ALL).title(" Error "))
        .style(Style::default().fg(Color::Red))
        .wrap(Wrap { trim: true });

    f.render_widget(error_widget, area);
}

// ============================================================================
// TESTS - R-WIDGET-COMPOSITION rendering tests
// ============================================================================

#[cfg(test)]
mod tests {
    use super::*;
    use ratatui::backend::TestBackend;
    use ratatui::Terminal;

    /// Helper to create a test backend
    fn create_test_terminal(width: u16, height: u16) -> Terminal<TestBackend> {
        let backend = TestBackend::new(width, height);
        Terminal::new(backend).expect("Failed to create test terminal")
    }

    /// Helper to render app and verify no panic
    fn render_app_safe(
        mut terminal: Terminal<TestBackend>,
        app: &App,
    ) -> Result<(), Box<dyn std::error::Error>> {
        terminal.draw(|f| {
            render(f, app);
        })?;

        Ok(())
    }

    #[test]
    fn test_render_empty_projects_list() {
        let app = App::new();
        assert!(app.projects.is_empty());

        let terminal = create_test_terminal(80, 24);
        let result = render_app_safe(terminal, &app);

        assert!(result.is_ok(), "Rendering empty projects should not panic");
    }

    #[test]
    fn test_render_with_projects() {
        let mut app = App::new();
        app.projects = vec![crate::types::ProjectDto {
            id: "1".to_string(),
            name: "Project 1".to_string(),
            version: "1.0.0".to_string(),
            project_type: "Web".to_string(),
            description: "Test project".to_string(),
            current_phase: "Development".to_string(),
            created_at: "2024-01-01".to_string(),
            updated_at: "2024-01-01".to_string(),
        }];

        let terminal = create_test_terminal(80, 24);
        let result = render_app_safe(terminal, &app);

        assert!(result.is_ok(), "Rendering with projects should work");
    }

    #[test]
    fn test_render_projects_screen_normal_terminal() {
        let app = App::new();
        let terminal = create_test_terminal(120, 30);
        let result = render_app_safe(terminal, &app);

        assert!(
            result.is_ok(),
            "Should render projects screen in normal terminal"
        );
    }

    #[test]
    fn test_render_projects_screen_small_terminal() {
        let app = App::new();
        let terminal = create_test_terminal(40, 10);
        let result = render_app_safe(terminal, &app);

        assert!(
            result.is_ok(),
            "Should render projects screen in small terminal"
        );
    }

    #[test]
    fn test_render_detail_screen() {
        let mut app = App::new();
        app.screen = Screen::ProjectDetail;
        app.current_project = Some(crate::types::ProjectDto {
            id: "1".to_string(),
            name: "Test Project".to_string(),
            version: "1.0.0".to_string(),
            project_type: "Web".to_string(),
            description: "A test project".to_string(),
            current_phase: "Review".to_string(),
            created_at: "2024-01-01".to_string(),
            updated_at: "2024-01-02".to_string(),
        });

        let terminal = create_test_terminal(80, 24);
        let result = render_app_safe(terminal, &app);

        assert!(result.is_ok(), "Should render detail screen");
    }

    #[test]
    fn test_render_security_screen() {
        let mut app = App::new();
        app.screen = Screen::Security;

        let terminal = create_test_terminal(80, 24);
        let result = render_app_safe(terminal, &app);

        assert!(result.is_ok(), "Should render security screen");
    }

    #[test]
    fn test_render_create_project_screen() {
        let mut app = App::new();
        app.screen = Screen::CreateProject;
        app.project_name_input = "My New Project".to_string();
        app.project_desc_input = "Description".to_string();

        let terminal = create_test_terminal(80, 24);
        let result = render_app_safe(terminal, &app);

        assert!(result.is_ok(), "Should render create project screen");
    }

    #[test]
    fn test_render_with_error() {
        let mut app = App::new();
        app.error = Some("An error occurred".to_string());

        let terminal = create_test_terminal(80, 24);
        let result = render_app_safe(terminal, &app);

        assert!(result.is_ok(), "Should render with error message");
    }

    #[test]
    fn test_render_loading_state() {
        let mut app = App::new();
        app.is_loading = true;

        let terminal = create_test_terminal(80, 24);
        let result = render_app_safe(terminal, &app);

        assert!(result.is_ok(), "Should render loading state");
    }

    #[test]
    fn test_render_preserves_app_state() {
        let mut app = App::new();
        app.screen = Screen::ProjectsList;
        app.project_name_input = "Original".to_string();
        app.project_desc_input = "Desc".to_string();
        app.is_loading = true;

        // Store original values
        let original_screen = app.screen;
        let original_name = app.project_name_input.clone();
        let original_desc = app.project_desc_input.clone();
        let original_loading = app.is_loading;

        // Render should not mutate state (R-WIDGET-COMPOSITION)
        let terminal = create_test_terminal(80, 24);
        let _ = render_app_safe(terminal, &app);

        assert_eq!(app.screen, original_screen);
        assert_eq!(app.project_name_input, original_name);
        assert_eq!(app.project_desc_input, original_desc);
        assert_eq!(app.is_loading, original_loading);
    }

    #[test]
    fn test_render_responsive_layout_various_sizes() {
        let app = App::new();

        let sizes = vec![(40, 10), (80, 24), (120, 40), (200, 60)];

        for (width, height) in sizes {
            let terminal = create_test_terminal(width, height);
            let result = render_app_safe(terminal, &app);

            assert!(
                result.is_ok(),
                "Should render responsively at {}x{}",
                width,
                height
            );
        }
    }

    #[test]
    fn test_render_long_project_name() {
        let mut app = App::new();
        app.projects = vec![crate::types::ProjectDto {
            id: "1".to_string(),
            name: "This is a very long project name that might cause layout issues in narrow terminals"
                .to_string(),
            version: "1.0.0".to_string(),
            project_type: "Web".to_string(),
            description: "Long description test".to_string(),
            current_phase: "Development".to_string(),
            created_at: "2024-01-01".to_string(),
            updated_at: "2024-01-01".to_string(),
        }];

        let terminal = create_test_terminal(60, 20);
        let result = render_app_safe(terminal, &app);

        assert!(
            result.is_ok(),
            "Should handle long project names with text wrapping"
        );
    }

    #[test]
    fn test_render_all_screens_in_sequence() {
        let mut app = App::new();

        let screens = vec![
            Screen::ProjectsList,
            Screen::ProjectDetail,
            Screen::Security,
            Screen::CreateProject,
        ];

        for screen in screens {
            app.screen = screen;

            let terminal = create_test_terminal(80, 24);
            let result = render_app_safe(terminal, &app);

            assert!(result.is_ok(), "Should render screen {:?}", screen);
        }
    }
}
