use super::ComponentManager;
use crate::app::AppState;
use crate::ui::style::{self, Emphasis};
use ratatui::Frame;
use ratatui::layout::{Constraint, Direction, Layout, Rect};
use ratatui::widgets::{Paragraph, List, ListItem, Clear, ListState};
use ratatui::text::{Line, Span};
use super::utils;

pub fn render_feedback(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    // Show feedback messages (success) or errors with guidance
    if let Some(ref feedback) = state.feedback_message {
        let footer_style = style::text(&state.theme, Emphasis::Success);
        let block = style::pane_block(&state.theme, "Status", false);
        let paragraph = Paragraph::new(feedback.clone())
            .style(footer_style)
            .block(block);

        let footer = Layout::default()
            .direction(Direction::Vertical)
            .constraints([Constraint::Min(0), Constraint::Length(3)])
            .split(area);
        frame.render_widget(paragraph, footer[1]);
        return;
    }

    // Show error with guidance if available
    if let Some(ref error_guidance) = state.error_guidance {
        let formatted = error_guidance.format_display();
        let lines: Vec<Line> = formatted
            .lines()
            .map(|line| {
                if line.starts_with("  [") && line.contains("]") {
                    // Format quick actions with highlighted keys
                    let parts: Vec<&str> = line.splitn(2, "] ").collect();
                    if parts.len() == 2 {
                        let key_part = parts[0].trim_start_matches("  [");
                        let label = parts[1];
                        Line::from(vec![
                            Span::styled("  [", style::text(&state.theme, Emphasis::Normal)),
                            Span::styled(key_part, style::text(&state.theme, Emphasis::Warning)),
                            Span::styled("] ", style::text(&state.theme, Emphasis::Normal)),
                            Span::styled(label, style::text(&state.theme, Emphasis::Normal)),
                        ])
                    } else {
                        Line::from(line)
                    }
                } else if line.starts_with("  •") {
                    // Format suggestions
                    // Find the character boundary after "  • " (which is 4 characters, not 4 bytes)
                    // The bullet character • is a multi-byte UTF-8 character, so we can't use byte indexing
                    let prefix = "  • ";
                    let char_count = prefix.chars().count();
                    let rest: String = line.chars().skip(char_count).collect();
                    Line::from(vec![
                        Span::styled(prefix, style::text(&state.theme, Emphasis::Muted)),
                        Span::styled(rest, style::text(&state.theme, Emphasis::Normal)),
                    ])
                } else if line == "Suggestions:" || line == "Quick actions:" {
                    // Format section headers
                    Line::from(vec![
                        Span::styled(line, style::text(&state.theme, Emphasis::Header)),
                    ])
                } else {
                    Line::from(line)
                }
            })
            .collect();

        let error_style = style::text(&state.theme, Emphasis::Error);
        let block = style::pane_block(&state.theme, "Error", false);
        let paragraph = Paragraph::new(lines)
            .style(error_style)
            .block(block);

        // Calculate height needed (at least 3, but more if guidance is long)
        let content_height = formatted.lines().count().max(3);
        let height = (content_height + 2).min(area.height as usize) as u16;

        let footer = Layout::default()
            .direction(Direction::Vertical)
            .constraints([Constraint::Min(0), Constraint::Length(height)])
            .split(area);
        frame.render_widget(paragraph, footer[1]);
        return;
    }

    // Fallback to simple error message if no guidance
    if let Some(ref error) = state.last_status_error {
        let footer_style = style::text(&state.theme, Emphasis::Error);
        let block = style::pane_block(&state.theme, "Status", false);
        let paragraph = Paragraph::new(error.clone())
            .style(footer_style)
            .block(block);

        let footer = Layout::default()
            .direction(Direction::Vertical)
            .constraints([Constraint::Min(0), Constraint::Length(3)])
            .split(area);
        frame.render_widget(paragraph, footer[1]);
    }
}

pub fn render_palette(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    let (items, selected, title) = if state.theme_picker {
        let max_idx = state.available_themes.len().saturating_sub(1);
        let selected = state.theme_picker_selected.min(max_idx);
        let items: Vec<ListItem> = state
            .available_themes
            .iter()
            .enumerate()
            .map(|(i, name)| {
                let style = if i == selected {
                    style::selection(&state.theme)
                } else {
                    style::text(&state.theme, Emphasis::Header)
                };
                ListItem::new(name.clone()).style(style)
            })
            .collect();
        let title = format!(
            "Themes [{} / {}]",
            selected.saturating_add(1),
            state.available_themes.len().max(1)
        );
        (items, selected, title)
    } else {
        // This branch should never be reached - new palette system handles all commands
        // Theme picker uses the if branch above
        (Vec::new(), 0, "Palette".to_string())
    };

    let popup = utils::center_rect(60, 40, area);
    let inner = popup;

    // Clear only the inner area to avoid large gutters.
    frame.render_widget(Clear, inner);

    let mut list_state = ListState::default();
    list_state.select(Some(selected));

    let list = List::new(items)
        .style(style::body_style(&state.theme))
        .block(style::pane_block(&state.theme, title, true));

    frame.render_stateful_widget(list, inner, &mut list_state);
}

pub fn render_theme_picker(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    let max_idx = state.available_themes.len().saturating_sub(1);
    let selected = state.theme_picker_selected.min(max_idx);

    let items: Vec<ListItem> = state
        .available_themes
        .iter()
        .enumerate()
        .map(|(i, name)| {
            let style = if i == selected {
                style::selection(&state.theme)
            } else {
                style::body_style(&state.theme)
            };
            ListItem::new(name.clone()).style(style)
        })
        .collect();

    let title = format!(
        "Themes [{} / {}]",
        selected.saturating_add(1),
        state.available_themes.len().max(1)
    );

    let popup = utils::center_rect(40, 60, area);
    frame.render_widget(Clear, popup);

    let list = List::new(items)
        .style(style::body_style(&state.theme))
        .block(style::pane_block(&state.theme, title, true));

    frame.render_widget(list, popup);
}

pub fn render_op_log(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    let popup = utils::center_rect(60, 30, area);
    frame.render_widget(Clear, popup);

    let lines: Vec<ratatui::widgets::ListItem> = state
        .op_log
        .iter()
        .rev()
        .take(10)
        .rev()
        .map(|l| ratatui::widgets::ListItem::new(l.clone()).style(style::text(&state.theme, style::Emphasis::Muted)))
        .collect();

    let title = "Op log (last 10) (Esc/q/Enter=close)";
    let list = ratatui::widgets::List::new(lines)
        .style(style::body_style(&state.theme))
        .block(style::pane_block(&state.theme, title.to_string(), true));

    frame.render_widget(list, popup);
}

pub fn render_merge_base_picker(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    let max_idx = state.merge_base_candidates.len().saturating_sub(1);
    let selected = state.merge_base_selected.min(max_idx);

    let items: Vec<ListItem> = state
        .merge_base_candidates
        .iter()
        .enumerate()
        .map(|(i, name)| {
            let style = if i == selected {
                style::selection(&state.theme)
            } else {
                style::body_style(&state.theme)
            };
            ListItem::new(name.clone()).style(style)
        })
        .collect();

    let title = "Pick merge base (Enter to apply, Esc to cancel)";
    let popup = utils::center_rect(40, 60, area);
    frame.render_widget(Clear, popup);

    let list = ratatui::widgets::List::new(items)
        .style(style::body_style(&state.theme))
        .block(style::pane_block(&state.theme, title.to_string(), true));

    frame.render_widget(list, popup);
}

pub fn render_conflicts_popup(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    let conflicts: Vec<&crate::git::parsers::status::StatusEntry> = state
        .status_entries
        .iter()
        .filter(|e| e.conflict)
        .collect();
    let max_idx = conflicts.len().saturating_sub(1);
    let selected = state.conflicts_popup_selected.min(max_idx);

    let items: Vec<ListItem> = if conflicts.is_empty() {
        vec![ListItem::new("No conflicts found").style(style::text(&state.theme, Emphasis::Muted))]
    } else {
        conflicts
            .iter()
            .enumerate()
            .map(|(i, entry)| {
                let style_item = if i == selected {
                    style::selection(&state.theme)
                } else {
                    style::body_style(&state.theme)
                };
                ListItem::new(entry.path.clone()).style(style_item)
            })
            .collect()
    };

    let title = format!(
        "Conflicts [{} / {}] (Enter=jump, o=open, Esc=close)",
        selected.saturating_add(1),
        conflicts.len().max(1)
    );
    let popup = utils::center_rect(50, 40, area);
    frame.render_widget(Clear, popup);

    let list = List::new(items)
        .style(style::body_style(&state.theme))
        .block(style::pane_block(&state.theme, title, true));

    frame.render_widget(list, popup);
}

pub fn render_conflicts_guided(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    let conflicts: Vec<&crate::git::parsers::status::StatusEntry> = state
        .status_entries
        .iter()
        .filter(|e| e.conflict)
        .collect();
    let max_idx = conflicts.len().saturating_sub(1);
    let selected = state.conflicts_guided_selected.min(max_idx);

    let width = 80;
    let height = 50;
    let popup = utils::center_rect(width, height, area);
    frame.render_widget(Clear, popup);

    // Split popup into list and instructions
    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([Constraint::Length(20), Constraint::Min(10)])
        .split(popup);

    // Conflict list
    let items: Vec<ListItem> = if conflicts.is_empty() {
        vec![ListItem::new("No conflicts").style(style::text(&state.theme, Emphasis::Muted))]
    } else {
        conflicts
            .iter()
            .enumerate()
            .map(|(i, entry)| {
                let style_item = if i == selected {
                    style::selection(&state.theme)
                } else {
                    style::body_style(&state.theme)
                };
                let indicator = if i == selected { "➤" } else { " " };
                let label = format!("{} {} ({}/{})", indicator, entry.path, i + 1, conflicts.len());
                ListItem::new(label).style(style_item)
            })
            .collect()
    };

    let title = format!(
        "Conflicts [{} / {}]",
        selected.saturating_add(1),
        conflicts.len().max(1)
    );
    let list = List::new(items)
        .style(style::body_style(&state.theme))
        .block(style::pane_block(&state.theme, title, true));

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

    // Step-by-step instructions with smart suggestions
    let instructions = if conflicts.is_empty() {
        vec![
            Line::from("No conflicts to resolve."),
        ]
    } else {
        let current = selected + 1;
        let total = conflicts.len();
        
        // Get smart suggestion for selected conflict
        let mut lines = vec![
            Line::from(vec![
                Span::styled("Step-by-Step Resolution Guide", style::text(&state.theme, Emphasis::Header)),
            ]),
            Line::from(""),
            Line::from(vec![
                Span::styled(format!("Resolving conflict {} of {}:", current, total), style::text(&state.theme, Emphasis::Normal)),
            ]),
            Line::from(""),
        ];
        
        // Add smart suggestion if available
        if let Some(conflict) = conflicts.get(selected) {
            if let Some(suggestion) = crate::app::conflict_resolution::ConflictSuggestion::analyze_conflict(
                &state.repo_path,
                &conflict.path
            ) {
                let suggestion_text = format!("💡 Suggestion: {}", suggestion.suggestion);
                lines.push(Line::from(vec![
                    Span::styled(suggestion_text, style::text(&state.theme, Emphasis::Warning)),
                ]));
                lines.push(Line::from(""));
            }
        }
        
        lines.extend(vec![
            Line::from("1. Open the conflict file in your editor:"),
            Line::from(vec![
                Span::styled("   [o] ", style::text(&state.theme, Emphasis::Warning)),
                Span::styled("Open in editor", style::text(&state.theme, Emphasis::Normal)),
            ]),
            Line::from(""),
            Line::from("2. Look for conflict markers in the file:"),
            Line::from(vec![
                Span::styled("   <<<<<<< HEAD", style::text(&state.theme, Emphasis::Error)),
            ]),
            Line::from("   (your changes)"),
            Line::from(vec![
                Span::styled("   =======", style::text(&state.theme, Emphasis::Error)),
            ]),
            Line::from("   (incoming changes)"),
            Line::from(vec![
                Span::styled("   >>>>>>> branch-name", style::text(&state.theme, Emphasis::Error)),
            ]),
            Line::from(""),
            Line::from("3. Choose one of these options:"),
            Line::from("   • Keep your changes (remove theirs)"),
            Line::from("   • Keep their changes (remove yours)"),
            Line::from("   • Keep both (merge manually)"),
            Line::from("   • Write a completely new version"),
            Line::from(""),
            Line::from("4. Remove all conflict markers (<<<<<<, ======, >>>>>>)"),
            Line::from(""),
            Line::from("5. Save the file and stage it:"),
            Line::from(vec![
                Span::styled("   [s] ", style::text(&state.theme, Emphasis::Warning)),
                Span::styled("Stage resolved file", style::text(&state.theme, Emphasis::Normal)),
            ]),
            Line::from(""),
            Line::from("6. Continue to next conflict or complete merge:"),
            Line::from(vec![
                Span::styled("   [n] ", style::text(&state.theme, Emphasis::Warning)),
                Span::styled("Next conflict", style::text(&state.theme, Emphasis::Normal)),
            ]),
            Line::from(vec![
                Span::styled("   [c] ", style::text(&state.theme, Emphasis::Warning)),
                Span::styled("Commit when all resolved", style::text(&state.theme, Emphasis::Normal)),
            ]),
        ]);
        
        lines
    };

    let instructions_paragraph = Paragraph::new(instructions)
        .style(style::text(&state.theme, Emphasis::Normal))
        .block(style::pane_block(&state.theme, "Instructions", false));

    frame.render_widget(instructions_paragraph, chunks[1]);
}

pub fn render_pr_helper(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    let max_idx = state.pr_list.len().saturating_sub(1);
    let selected = state.pr_selected.min(max_idx);

    let items: Vec<ListItem> = if state.pr_list.is_empty() {
        vec![ListItem::new("No PRs found").style(style::text(&state.theme, Emphasis::Muted))]
    } else {
        state
            .pr_list
            .iter()
            .enumerate()
            .map(|(i, pr)| {
                let style_item = if i == selected {
                    style::selection(&state.theme)
                } else {
                    style::body_style(&state.theme)
                };
                ListItem::new(format!("#{} {}", pr.number, pr.title)).style(style_item)
            })
            .collect()
    };

    let title = format!(
        "PR helper [{} / {}] (Enter=checkout, o=open, Esc=close)",
        selected.saturating_add(1),
        state.pr_list.len().max(1)
    );
    let popup = utils::center_rect(60, 50, area);
    frame.render_widget(Clear, popup);

    let list = List::new(items)
        .style(style::body_style(&state.theme))
        .block(style::pane_block(&state.theme, title.to_string(), true));

    frame.render_widget(list, popup);
}

pub fn render_log_action_menu(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    tracing::debug!(
        "render_log_action_menu: called, log_action_menu={}, commit_hash={:?}",
        state.log_action_menu,
        state.log_action_commit_hash
    );

    use crate::app::actions::LogAction;

    // Determine if sensitive actions are blocked.
    let dirty = state
        .status_entries
        .iter()
        .any(|e| e.staged || e.unstaged || e.conflict || (!e.staged && !e.unstaged && !e.conflict));
    let in_progress = state.workflow_context.as_ref().map_or(false, |ctx| {
        matches!(
            ctx.state,
            crate::app::workflow::WorkflowState::RebaseInProgress
                | crate::app::workflow::WorkflowState::CherryPickInProgress
                | crate::app::workflow::WorkflowState::MergeInProgress
                | crate::app::workflow::WorkflowState::Conflicts
        )
    });
    let block_reason = if in_progress {
        Some("blocked: rebase/cherry-pick/merge/conflicts in progress")
    } else if dirty {
        Some("blocked: requires clean working tree")
    } else {
        None
    };

    // Use the same source as the handler to avoid divergence.
    let actions: Vec<LogAction> = super::event_handlers::get_available_log_actions(state);

    // Map actions to display labels, keeping blocked ones visible.
    let action_labels: Vec<(String, bool)> = actions
        .iter()
        .map(|action| {
            let base = match action {
                LogAction::ShowDetail => "Show detail",
                LogAction::CherryPick => "Cherry-pick",
                LogAction::Revert => "Revert",
                LogAction::Amend => "Amend (HEAD only)",
                LogAction::ResetSoft => "Reset to here (soft)",
                LogAction::ResetMixed => "Reset to here (mixed)",
                LogAction::ResetHard => "Reset to here (hard)",
                LogAction::CreateBranch => "Create branch",
                LogAction::CreateTag => "Create tag",
            };

            let blocked = matches!(
                action,
                LogAction::CherryPick
                    | LogAction::Revert
                    | LogAction::ResetSoft
                    | LogAction::ResetMixed
                    | LogAction::ResetHard
            ) && block_reason.is_some();

            let label = if blocked {
                format!("{base} ({})", block_reason.unwrap_or_default())
            } else {
                base.to_string()
            };
            (label, blocked)
        })
        .collect();
    
    let max_idx = actions.len().saturating_sub(1);
    let selected = state.log_action_selected.min(max_idx);
    
    let items: Vec<ListItem> = action_labels
        .iter()
        .enumerate()
        .map(|(i, (label, blocked))| {
            let style_item = if i == selected {
                style::selection(&state.theme)
            } else if *blocked {
                style::text(&state.theme, Emphasis::Muted)
            } else {
                style::body_style(&state.theme)
            };
            ListItem::new(label.as_str()).style(style_item)
        })
        .collect();
    
    let commit_info = if let Some(hash) = &state.log_action_commit_hash {
        if let Some(commit) = state.commits.iter().find(|c| c.hash == *hash) {
            format!("{} - {}", commit.short_hash, commit.message)
        } else {
            hash.clone()
        }
    } else {
        "Unknown commit".to_string()
    };
    
    // Eligibility hints for cherry-pick/revert
    let clean_hint = if let Some(reason) = block_reason {
        reason
    } else {
        "Ready: clean working tree"
    };

    let title = format!("Actions for: {}", commit_info);
    let popup_height = (actions.len() + 7).min(28) as u16;
    let popup = utils::center_rect(80, popup_height, area);
    frame.render_widget(Clear, popup);
    
    let list = List::new(items)
        .style(style::body_style(&state.theme))
        .block(style::pane_block(&state.theme, title, true));
    
    frame.render_widget(list, popup);

    // Render a footer hint about eligibility just below the list area
    let footer_area = Rect {
        x: popup.x,
        y: popup.y.saturating_add(popup.height.saturating_sub(2)),
        width: popup.width,
        height: 2,
    };
    let footer = Paragraph::new(clean_hint).style(style::body_style(&state.theme));
    frame.render_widget(footer, footer_area);

    // Confirmation modal (if any)
    if let Some(msg) = &state.confirm_message {
        let confirm_area = utils::center_rect(50, 20, area);
        frame.render_widget(Clear, confirm_area);
        let block = style::pane_block(&state.theme, "Confirm", true);
        let text = format!("{msg}\n\nEnter = confirm   Esc = cancel");
        let para = Paragraph::new(text)
            .style(style::body_style(&state.theme))
            .block(block);
        frame.render_widget(para, confirm_area);
    }

    // Interactive rebase builder (new)
    if state.rebase_editor_open {
        render_rebase_builder(_manager, frame, area, state);
    }
}

pub fn render_rebase_todo(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    let max_idx = state.rebase_todo.len().saturating_sub(1);
    let selected = state.rebase_todo_selected.min(max_idx);

    let items: Vec<ListItem> = if state.rebase_todo.is_empty() {
        vec![ListItem::new("No rebase todo").style(style::text(&state.theme, Emphasis::Muted))]
    } else {
        state
            .rebase_todo
            .iter()
            .enumerate()
            .map(|(i, line)| {
                let display = if state.rebase_todo_editing && i == selected {
                    format!("{}{}", state.rebase_todo_edit_buffer, "  [editing]")
                } else {
                    line.clone()
                };
                let style_item = if i == selected {
                    style::selection(&state.theme)
                } else {
                    style::body_style(&state.theme)
                };
                ListItem::new(display).style(style_item)
            })
            .collect()
    };

    let title = format!(
        "Rebase todo{} [{} / {}] (Enter=edit, p/e/s/f/d/w toggle, x=skip, c=continue, a=abort, S=save, o=editor, Esc=close)",
        if state.rebase_todo_dirty { " *" } else { "" },
        selected.saturating_add(1),
        state.rebase_todo.len().max(1)
    );
    let popup = utils::center_rect(60, 50, area);
    frame.render_widget(Clear, popup);

    let list = List::new(items)
        .style(style::body_style(&state.theme))
        .block(style::pane_block(&state.theme, title, true));

    frame.render_widget(list, popup);
}

/// Standalone interactive rebase builder popup.
pub fn render_rebase_builder(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    let popup = utils::center_rect(70, 60, area);
    frame.render_widget(Clear, popup);

    let title = format!(
        "Interactive rebase [{} / {}] (Enter=save/run, Esc=cancel, j/k=nav, [ ]=move, left/right=cycle action)",
        state.rebase_cursor.saturating_add(1),
        state.rebase_entries.len().max(1)
    );
    let mut lines: Vec<ListItem> = Vec::new();
    for (i, entry) in state.rebase_entries.iter().enumerate() {
        let action_label = match entry.action {
            crate::app::state::RebaseAction::Pick => "pick",
            crate::app::state::RebaseAction::Reword => "reword",
            crate::app::state::RebaseAction::Edit => "edit",
            crate::app::state::RebaseAction::Squash => "squash",
            crate::app::state::RebaseAction::Fixup => "fixup",
            crate::app::state::RebaseAction::Drop => "drop",
        };
        let marker = if i == state.rebase_cursor { "▶ " } else { "  " };
        let display_msg = if matches!(entry.action, crate::app::state::RebaseAction::Reword) {
            let msg = state
                .reword_message
                .as_ref()
                .filter(|m| !m.trim().is_empty())
                .cloned()
                .unwrap_or_else(|| entry.message.clone());
            let author = state
                .reword_author_name
                .as_ref()
                .filter(|a| !a.trim().is_empty())
                .and_then(|name| {
                    state
                        .reword_author_email
                        .as_ref()
                        .filter(|e| !e.trim().is_empty())
                        .map(|email| format!("{} <{}>", name, email))
                        .or_else(|| Some(name.clone()))
                });
            if let Some(auth) = author {
                format!("{}  [author: {}]", msg, auth)
            } else {
                msg
            }
        } else {
            entry.message.clone()
        };
        let text = format!("{marker}{:<6} {:<8} {}", action_label, entry.short_hash, display_msg);
        let style_item = if i == state.rebase_cursor {
            style::selection(&state.theme)
        } else {
            style::body_style(&state.theme)
        };
        lines.push(ListItem::new(text).style(style_item));
    }
    let list = List::new(lines)
        .style(style::body_style(&state.theme))
        .block(style::pane_block(&state.theme, title, true));
    frame.render_widget(list, popup);

    // Footer with base and selection count
    let base_display = state
        .rebase_base
        .clone()
        .or_else(|| state.rebase_entries.last().map(|e| e.hash.clone()))
        .unwrap_or_else(|| "unknown".to_string());
    let selected_count = state.log_selected_hashes.len();
    let has_edit = state
        .rebase_entries
        .iter()
        .any(|e| matches!(e.action, crate::app::state::RebaseAction::Edit));
    let edit_note = if has_edit {
        " Edit steps will pause; make changes then run rebase --continue/--skip/--abort (A abort)."
    } else {
        ""
    };
    let footer_text = format!(
        "Base: {}^   Selected: {}   Enter=save/run  Esc=cancel  j/k=nav  [ ]=move  ←/→=action  v=select  b=set base  Note: rebase is paused; run rebase --continue after saving.{}",
        base_display,
        selected_count,
        edit_note
    );
    let footer_area = Rect {
        x: popup.x,
        y: popup.y.saturating_add(popup.height.saturating_sub(2)),
        width: popup.width,
        height: 2,
    };
    let footer = Paragraph::new(footer_text).style(style::body_style(&state.theme));
    frame.render_widget(footer, footer_area);

    if state.rebase_dirty {
        let dirty_note = Paragraph::new("Unsaved changes").style(style::text(&state.theme, Emphasis::Warning));
        let note_area = Rect {
            x: popup.x,
            y: popup.y.saturating_add(popup.height.saturating_sub(1)),
            width: popup.width,
            height: 1,
        };
        frame.render_widget(dirty_note, note_area);
    }
}

/// Inline reword modal (editorless reword message).
pub fn render_reword_modal(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    if !state.reword_modal_open {
        return;
    }
    let popup = utils::center_rect(70, 20, area);
    frame.render_widget(Clear, popup);
    let block = style::pane_block(
        &state.theme,
        "Reword: message + optional author (Enter=save/close, Esc=cancel, Ctrl+M=msg, Ctrl+N=name, Ctrl+E=email)",
        true,
    );

    let msg = state.reword_message.clone().unwrap_or_default();
    let author_name = state.reword_author_name.clone().unwrap_or_else(|| "".to_string());
    let author_name_display = if author_name.is_empty() { "<name: optional>".to_string() } else { author_name };
    let author_email = state.reword_author_email.clone().unwrap_or_else(|| "".to_string());
    let author_email_display = if author_email.is_empty() { "<email: optional>".to_string() } else { author_email };

    // Highlight the currently focused field
    let (msg_prefix, name_prefix, email_prefix) = match state.reword_focus_field {
        crate::app::state::RewordField::Message => ("▶ Message:", "  Author: ", "  Email:  "),
        crate::app::state::RewordField::AuthorName => ("  Message:", "▶ Author: ", "  Email:  "),
        crate::app::state::RewordField::AuthorEmail => ("  Message:", "  Author: ", "▶ Email:  "),
    };

    let lines = vec![
        format!("{}{}", msg_prefix, msg),
        format!("{}{}", name_prefix, author_name_display),
        format!("{}{}", email_prefix, author_email_display),
        "".to_string(),
        "Type to edit focused field. Ctrl+M=focus message; Ctrl+N=focus author name; Ctrl+E=focus author email.".to_string(),
    ];

    let para = Paragraph::new(lines.join("\n"))
        .style(style::body_style(&state.theme))
        .block(block);
    frame.render_widget(para, popup);
}

pub fn render_edit_modal(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    if !state.edit_modal_open {
        return;
    }
    let popup = utils::center_rect(70, 20, area);
    frame.render_widget(Clear, popup);
    let block = style::pane_block(
        &state.theme,
        "Edit: message + optional author + file changes (Enter=save/close, Esc=cancel, Ctrl+M=msg, Ctrl+N=name, Ctrl+E=email)",
        true,
    );

    let msg = state.edit_message.clone().unwrap_or_default();
    let author_name = state.edit_author_name.clone().unwrap_or_else(|| "".to_string());
    let author_name_display = if author_name.is_empty() { "<name: optional>".to_string() } else { author_name };
    let author_email = state.edit_author_email.clone().unwrap_or_else(|| "".to_string());
    let author_email_display = if author_email.is_empty() { "<email: optional>".to_string() } else { author_email };

    // Highlight the currently focused field
    let (msg_prefix, name_prefix, email_prefix) = match state.edit_focus_field {
        crate::app::state::RewordField::Message => ("▶ Message:", "  Author: ", "  Email:  "),
        crate::app::state::RewordField::AuthorName => ("  Message:", "▶ Author: ", "  Email:  "),
        crate::app::state::RewordField::AuthorEmail => ("  Message:", "  Author: ", "▶ Email:  "),
    };

    let lines = vec![
        format!("{}{}", msg_prefix, msg),
        format!("{}{}", name_prefix, author_name_display),
        format!("{}{}", email_prefix, author_email_display),
        "".to_string(),
        "Type to edit focused field. Ctrl+M=focus message; Ctrl+N=focus author name; Ctrl+E=focus author email.".to_string(),
    ];

    let para = Paragraph::new(lines.join("\n"))
        .style(style::body_style(&state.theme))
        .block(block);
    frame.render_widget(para, popup);
}

pub fn render_merge_log(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    let popup = utils::center_rect(60, 30, area);
    frame.render_widget(Clear, popup);

    let lines: Vec<ratatui::widgets::ListItem> = state
        .merge_notifier_log
        .iter()
        .rev()
        .take(15)
        .rev()
        .map(|l| ratatui::widgets::ListItem::new(l.clone()).style(style::text(&state.theme, style::Emphasis::Muted)))
        .collect();

    let title = "Merge notifier log";
    let list = ratatui::widgets::List::new(lines)
        .style(style::body_style(&state.theme))
        .block(style::pane_block(&state.theme, title.to_string(), true));

    frame.render_widget(list, popup);
}

pub fn render_commit_input(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    // Calculate popup height based on whether we're in amend mode
    let popup_height = if state.amend_mode && state.last_commit_info.is_some() {
        20 // More space for amend info
    } else {
        15
    };
    
    let popup = utils::center_rect(80, popup_height, area);
    frame.render_widget(Clear, popup);

    let title = if state.amend_mode {
        "Amend commit (Tab=switch field, Enter=amend, Esc=cancel)"
    } else {
        "Commit message (Enter=submit, Esc=cancel)"
    };
    
    // Create layout: header with last commit info (if amend), then commit message input
    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints(if state.amend_mode && state.last_commit_info.is_some() {
            vec![Constraint::Length(6), Constraint::Min(1)]
        } else {
            vec![Constraint::Min(1)]
        })
        .split(popup);
    
    // Show last commit info if amending
    if state.amend_mode {
        if let Some(ref last_info) = state.last_commit_info {
            let info_text = vec![
                Line::from(vec![
                    Span::styled("Last commit: ", style::text(&state.theme, Emphasis::Muted)),
                    Span::styled(&last_info.short_hash, style::text(&state.theme, Emphasis::Normal)),
                ]),
                Line::from(vec![
                    Span::styled("Author: ", style::text(&state.theme, Emphasis::Muted)),
                    Span::styled(&last_info.author_name, style::text(&state.theme, Emphasis::Normal)),
                    Span::styled(" <", style::text(&state.theme, Emphasis::Muted)),
                    Span::styled(&last_info.author_email, style::text(&state.theme, Emphasis::Normal)),
                    Span::styled(">", style::text(&state.theme, Emphasis::Muted)),
                ]),
                Line::from(vec![
                    Span::styled("Date: ", style::text(&state.theme, Emphasis::Muted)),
                    Span::styled(&last_info.date, style::text(&state.theme, Emphasis::Normal)),
                ]),
                Line::from(""),
                Line::from({
                    let name_style = if state.amend_editing_field == Some(crate::app::state::AmendField::AuthorName) {
                        style::selection(&state.theme)
                    } else {
                        style::text(&state.theme, Emphasis::Normal)
                    };
                    vec![
                        Span::styled("Author Name: ", style::text(&state.theme, Emphasis::Muted)),
                        Span::styled(&state.amend_author_name, name_style),
                        if state.amend_editing_field == Some(crate::app::state::AmendField::AuthorName) {
                            Span::styled(" ▊", style::text(&state.theme, Emphasis::Normal))
                        } else {
                            Span::raw("")
                        },
                    ]
                }),
                Line::from({
                    let email_style = if state.amend_editing_field == Some(crate::app::state::AmendField::AuthorEmail) {
                        style::selection(&state.theme)
                    } else {
                        style::text(&state.theme, Emphasis::Normal)
                    };
                    vec![
                        Span::styled("Author Email: ", style::text(&state.theme, Emphasis::Muted)),
                        Span::styled(&state.amend_author_email, email_style),
                        if state.amend_editing_field == Some(crate::app::state::AmendField::AuthorEmail) {
                            Span::styled(" ▊", style::text(&state.theme, Emphasis::Normal))
                        } else {
                            Span::raw("")
                        },
                    ]
                }),
            ];
            
            let info_block = style::pane_block(&state.theme, "Last Commit Info".to_string(), false);
            let info_paragraph = Paragraph::new(info_text)
                .style(style::body_style(&state.theme))
                .block(info_block);
            frame.render_widget(info_paragraph, chunks[0]);
        }
    }
    
    let block = style::pane_block(&state.theme, title.to_string(), true);
    let message_style = if state.amend_mode
        && state.amend_editing_field != Some(crate::app::state::AmendField::AuthorName)
        && state.amend_editing_field != Some(crate::app::state::AmendField::AuthorEmail)
    {
        style::selection(&state.theme)
    } else {
        style::body_style(&state.theme)
    };
    
    let message_text = if state.amend_mode && state.amend_editing_field == Some(crate::app::state::AmendField::Message) {
        format!("{}{}", state.commit_input, "▊")
    } else {
        state.commit_input.clone()
    };
    
    let paragraph = Paragraph::new(message_text)
        .style(message_style)
        .block(block);

    frame.render_widget(paragraph, chunks[chunks.len() - 1]);

    // Inline validation for amend fields
    if state.amend_mode {
        let mut issues = Vec::new();
        if state.commit_input.trim().is_empty() {
            issues.push("Commit message is required");
        }
        if state.amend_author_name.trim().is_empty() {
            issues.push("Author name is required");
        }
        if state.amend_author_email.trim().is_empty() {
            issues.push("Author email is required");
        }
        if !issues.is_empty() {
            let issues_text = issues.join(" • ");
            let hint_area = Rect {
                x: popup.x,
                y: popup.y.saturating_add(popup.height.saturating_sub(2)),
                width: popup.width,
                height: 2,
            };
            let hint = Paragraph::new(format!("Issues: {issues_text}"))
                .style(style::body_style(&state.theme));
            frame.render_widget(hint, hint_area);
        }
    }
}

pub fn render_branch_create_input(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    let popup = utils::center_rect(60, 10, area);
    frame.render_widget(Clear, popup);

    let title = "New branch name (Enter=create, Esc=cancel)";
    let block = style::pane_block(&state.theme, title.to_string(), true);
    let paragraph = Paragraph::new(state.branch_name_input.as_str())
        .style(style::body_style(&state.theme))
        .block(block);

    frame.render_widget(paragraph, popup);
}

pub fn render_stash_create_input(_manager: &ComponentManager, frame: &mut Frame, area: Rect, state: &AppState) {
    let popup = utils::center_rect(60, 10, area);
    frame.render_widget(Clear, popup);

    let title = "Stash message (Enter=create, Esc=cancel)";
    let block = style::pane_block(&state.theme, title.to_string(), true);
    let paragraph = Paragraph::new(state.stash_message_input.as_str())
        .style(style::body_style(&state.theme))
        .block(block);

    frame.render_widget(paragraph, popup);
}

// Workflow assistant UI removed to avoid bloat
// Workflow detection logic is still used for smart palette suggestions