bath 0.4.0

A TUI tool to manage and export environment variable profiles
use crate::tui::util::{is_ctrl_c, next_key_press};
use anyhow::Result;
use crossterm::event::{KeyCode, KeyModifiers};
use ratatui::{
    backend::Backend,
    layout::{Constraint, Layout, Rect},
    style::Style,
    widgets::{Block, Borders, Paragraph},
    Terminal,
};
use std::time::Duration;

pub fn edit_profile_name_dialog<B: Backend>(
    terminal: &mut Terminal<B>,
    initial: Option<&str>,
) -> Result<Option<String>> {
    let mut name = initial.unwrap_or("").to_string();
    loop {
        terminal.draw(|f| {
            let area = centered_rect(50, 20, f.size());
            let block = Block::default()
                .borders(Borders::ALL)
                .title("Profile Name (Enter: confirm, Esc: cancel)");
            let paragraph = Paragraph::new(format!("Profile Name: {}", name))
                .block(block)
                .style(Style::default());
            f.render_widget(paragraph, area);
        })?;
        if let Some(key) = next_key_press(Duration::from_millis(100))? {
            // Ctrl+C cancels like Esc so the global quit chord is never dead here.
            if is_ctrl_c(&key) {
                return Ok(None);
            }
            match key.code {
                KeyCode::Enter => {
                    // Reject empty/whitespace-only names: stay in the dialog
                    // until the user types a real name or cancels with Esc.
                    let trimmed = name.trim();
                    if !trimmed.is_empty() {
                        return Ok(Some(trimmed.to_string()));
                    }
                }
                KeyCode::Esc => return Ok(None),
                KeyCode::Backspace => {
                    name.pop();
                }
                KeyCode::Char(c) if !key.modifiers.contains(KeyModifiers::CONTROL) => {
                    name.push(c);
                }
                _ => {}
            }
        }
    }
}

fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
    let popup_layout = Layout::default()
        .direction(ratatui::layout::Direction::Vertical)
        .constraints(
            [
                Constraint::Percentage((100 - percent_y) / 2),
                Constraint::Percentage(percent_y),
                Constraint::Percentage((100 - percent_y) / 2),
            ]
            .as_ref(),
        )
        .split(r);
    let horizontal = Layout::default()
        .direction(ratatui::layout::Direction::Horizontal)
        .constraints(
            [
                Constraint::Percentage((100 - percent_x) / 2),
                Constraint::Percentage(percent_x),
                Constraint::Percentage((100 - percent_x) / 2),
            ]
            .as_ref(),
        )
        .split(popup_layout[1]);
    horizontal[1]
}

/// Displays a confirmation popup with the given message.
/// Returns true if the user presses Y, false if N or Esc.
pub fn confirm_dialog<B: Backend>(terminal: &mut Terminal<B>, message: &str) -> Result<bool> {
    loop {
        terminal.draw(|f| {
            let area = centered_rect(50, 20, f.size());
            let block = Block::default().borders(Borders::ALL).title("Confirmation");
            let paragraph = Paragraph::new(format!(
                "{}\n\nPress Y to confirm, N or Esc to cancel",
                message
            ))
            .block(block)
            .style(Style::default());
            f.render_widget(paragraph, area);
        })?;
        if let Some(key) = next_key_press(Duration::from_millis(100))? {
            // Ctrl+C cancels like Esc so the global quit chord is never dead here.
            if is_ctrl_c(&key) {
                return Ok(false);
            }
            match key.code {
                KeyCode::Char('y') | KeyCode::Char('Y') => return Ok(true),
                KeyCode::Char('n') | KeyCode::Char('N') | KeyCode::Esc => return Ok(false),
                _ => {}
            }
        }
    }
}