tuitab 0.4.2

Terminal tabular data explorer — CSV/JSON/Parquet/Excel/SQLite viewer with filtering, sorting, pivot tables, and charts
use crate::theme::EverforestTheme as T;
use crate::ui::popup::centered_rect;
use ratatui::{
    layout::Rect,
    style::Style,
    widgets::{Block, Borders, Clear, List, ListItem},
    Frame,
};

pub fn render_join_overview_select_popup(frame: &mut Frame, app: &crate::app::App, area: Rect) {
    let popup_area = centered_rect(55, 65, area);
    frame.render_widget(Clear, popup_area);

    let items = &app.join.context_items;
    let cursor = app.join.overview_cursor;
    let selected = &app.join.overview_selected;
    let n_selected = selected.len();

    let list_items: Vec<ListItem> = items
        .iter()
        .enumerate()
        .map(|(i, item)| {
            let is_cursor = i == cursor;
            let is_sel = selected.contains(&i);
            let check = if is_sel { "[✓]" } else { "[ ]" };
            let arrow = if is_cursor { "" } else { "  " };
            let text = format!("{}{} {}", arrow, check, item.label());
            let style = if is_cursor && is_sel {
                Style::default().fg(T::YELLOW).bg(T::BG2)
            } else if is_cursor {
                Style::default().fg(T::FG).bg(T::BG2)
            } else if is_sel {
                Style::default().fg(T::GREEN)
            } else {
                Style::default().fg(T::FG)
            };
            ListItem::new(text).style(style)
        })
        .collect();

    let title = format!(
        " JOIN: select items — {} selected (Space=toggle, Enter=confirm) ",
        n_selected
    );
    let list = List::new(list_items).block(
        Block::default()
            .title(title)
            .borders(Borders::ALL)
            .border_style(Style::default().fg(T::PURPLE)),
    );
    frame.render_widget(list, popup_area);
}

pub fn render_join_source_popup(frame: &mut Frame, app: &crate::app::App, area: Rect) {
    let popup_area = centered_rect(50, 60, area);
    frame.render_widget(Clear, popup_area);

    let ctx_items = &app.join.context_items;
    let ctx_count = ctx_items.len();
    let other_titles = app.stack.sheet_titles_except_active();
    let mut items: Vec<ListItem> = Vec::new();

    let browse_active = app.join.source_index == 0;
    let prefix = if browse_active { "" } else { "  " };
    let style = if browse_active {
        Style::default().fg(T::YELLOW).bg(T::BG2)
    } else {
        Style::default().fg(T::FG)
    };
    items.push(ListItem::new(format!("{}[Browse file...]", prefix)).style(style));

    for (i, ctx) in ctx_items.iter().enumerate() {
        let idx = i + 1;
        let is_active = idx == app.join.source_index;
        let pfx = if is_active { "" } else { "  " };
        let style = if is_active {
            Style::default().fg(T::YELLOW).bg(T::BG2)
        } else {
            Style::default().fg(T::GREEN)
        };
        items.push(ListItem::new(format!("{}{}", pfx, ctx.label())).style(style));
    }

    for (i, title) in other_titles.iter().enumerate() {
        let idx = i + 1 + ctx_count;
        let is_active = idx == app.join.source_index;
        let pfx = if is_active { "" } else { "  " };
        let style = if is_active {
            Style::default().fg(T::YELLOW).bg(T::BG2)
        } else {
            Style::default().fg(T::FG)
        };
        items.push(ListItem::new(format!("{}{}", pfx, title)).style(style));
    }

    let list = List::new(items).block(
        Block::default()
            .title(" JOIN: Select source (↑↓, Enter) ")
            .borders(Borders::ALL)
            .border_style(Style::default().fg(T::PURPLE)),
    );
    frame.render_widget(list, popup_area);
}

pub fn render_join_type_popup(frame: &mut Frame, app: &crate::app::App, area: Rect) {
    use crate::data::join::JoinType;
    let popup_area = centered_rect(40, 35, area);
    frame.render_widget(Clear, popup_area);

    let items: Vec<ListItem> = JoinType::all()
        .iter()
        .enumerate()
        .map(|(i, jt)| {
            let is_active = i == app.join.type_index;
            let prefix = if is_active { "" } else { "  " };
            let style = if is_active {
                Style::default().fg(T::YELLOW).bg(T::BG2)
            } else {
                Style::default().fg(T::FG)
            };
            ListItem::new(format!("{}{}", prefix, jt.label())).style(style)
        })
        .collect();

    let list = List::new(items).block(
        Block::default()
            .title(" JOIN: Select join type (↑↓, Enter) ")
            .borders(Borders::ALL)
            .border_style(Style::default().fg(T::PURPLE)),
    );
    frame.render_widget(list, popup_area);
}

pub fn render_join_key_popup(
    frame: &mut Frame,
    title: &str,
    columns: &[String],
    selected_keys: &[String],
    cursor_index: usize,
    area: Rect,
) {
    let popup_area = centered_rect(45, 60, area);
    frame.render_widget(Clear, popup_area);

    let items: Vec<ListItem> = columns
        .iter()
        .enumerate()
        .map(|(i, col)| {
            let is_selected = selected_keys.contains(col);
            let is_active = i == cursor_index;
            let order = selected_keys
                .iter()
                .position(|k| k == col)
                .map(|p| (p + 1).to_string())
                .unwrap_or_default();
            let checkbox = if is_selected {
                format!("[{}]", order)
            } else {
                "[ ]".to_string()
            };
            let prefix = if is_active { "> " } else { "  " };
            let text = format!("{}{} {}", prefix, checkbox, col);
            let mut style = Style::default().fg(T::FG);
            if is_selected {
                style = style.fg(T::GREEN);
            }
            if is_active {
                style = style.bg(T::BG2);
            }
            ListItem::new(text).style(style)
        })
        .collect();

    let list = List::new(items).block(
        Block::default()
            .title(format!(" {} (Space toggle, Enter apply) ", title))
            .borders(Borders::ALL)
            .border_style(Style::default().fg(T::PURPLE)),
    );
    frame.render_widget(list, popup_area);
}