//! Shared TUI components used by both client and server.

use std::io::{self, stdout};

use crossterm::ExecutableCommand;
use crossterm::terminal::{
    EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode,
};
use ratatui::prelude::*;
use ratatui::widgets::*;

/// RAII guard for terminal state. Enters raw mode and alternate screen on
/// creation, restores both on drop.
pub struct TerminalGuard {
    pub terminal: Terminal<CrosstermBackend<io::Stdout>>,
}

impl TerminalGuard {
    pub fn new() -> Self {
        enable_raw_mode().unwrap();
        stdout().execute(EnterAlternateScreen).unwrap();
        let terminal = Terminal::new(CrosstermBackend::new(stdout())).unwrap();
        Self { terminal }
    }
}

impl Drop for TerminalGuard {
    fn drop(&mut self) {
        let _ = disable_raw_mode();
        let _ = stdout().execute(LeaveAlternateScreen);
    }
}

/// Render a centered modal dialog over the existing UI.
///
/// Buttons are rendered with reversed/bold styling to look interactive.
///
/// ```text
/// ┌─ Title ────────────────────┐
/// │     Some message here.     │
/// │                            │
/// │   ▌ OK (Enter) ▐  ▌ Cancel ▐ │
/// └────────────────────────────┘
/// ```
pub fn render_modal(f: &mut ratatui::Frame, title: &str, message: &str, buttons: &[&str]) {
    let button_line: String = buttons
        .iter()
        .map(|b| format!(" {b} "))
        .collect::<Vec<_>>()
        .join("  ");

    let area = f.area();
    let width = (message.len() as u16 + 4)
        .max(button_line.len() as u16 + 4)
        .max(title.len() as u16 + 6)
        .min(area.width);
    let height = 5;
    let x = area.width.saturating_sub(width) / 2;
    let y = area.height.saturating_sub(height) / 2;
    let modal_area = Rect::new(x, y, width, height);

    f.render_widget(Clear, modal_area);

    let button_spans: Vec<Span> = buttons
        .iter()
        .enumerate()
        .flat_map(|(i, b)| {
            let btn = Span::styled(
                format!(" {b} "),
                Style::default()
                    .add_modifier(Modifier::REVERSED)
                    .add_modifier(Modifier::BOLD),
            );
            if i > 0 {
                vec![Span::raw("  "), btn]
            } else {
                vec![btn]
            }
        })
        .collect();

    let text = vec![
        Line::from(message).centered(),
        Line::from(""),
        Line::from(button_spans).centered(),
    ];
    let modal = Paragraph::new(text).block(Block::bordered().title(title));
    f.render_widget(modal, modal_area);
}

/// Render the standard two-pane layout: scrolling message log on top, input on bottom.
pub fn render_chat_layout(
    f: &mut ratatui::Frame,
    messages: &[String],
    input: &str,
    log_title: &str,
    input_title: &str,
) {
    let chunks =
        Layout::vertical([Constraint::Min(1), Constraint::Length(3)]).split(f.area());

    let visible_height = chunks[0].height.saturating_sub(2) as usize;
    let scroll = messages.len().saturating_sub(visible_height) as u16;

    let messages_widget = Paragraph::new(
        messages
            .iter()
            .map(|m| Line::from(m.as_str()))
            .collect::<Vec<_>>(),
    )
    .block(Block::bordered().title(log_title))
    .wrap(Wrap { trim: false })
    .scroll((scroll, 0));

    let input_widget = Paragraph::new(input).block(Block::bordered().title(input_title));

    f.render_widget(messages_widget, chunks[0]);
    f.render_widget(input_widget, chunks[1]);
}
