use crate::config::colors::themes::Theme;
use ratatui::{
    layout::{Constraint, Direction, Layout, Margin, Rect},
    prelude::Alignment,
    style::{Modifier, Style},
    text::{Line, Span, Text},
    widgets::{Block, BorderType, Borders, Paragraph, Clear},
    Frame,
};
use unicode_segmentation::UnicodeSegmentation; // For grapheme clusters
use unicode_width::UnicodeWidthStr; // For accurate width calculation

pub fn render_dialog(
    f: &mut Frame,
    area: Rect,
    theme: &Theme,
    dialog_title: &str,
    dialog_message: &str,
    dialog_buttons: &[String],
    dialog_active_button_index: usize,
    is_loading: bool,
) {
    // Calculate required height based on the actual number of lines in the message
    let message_lines: Vec<_> = dialog_message.lines().collect();
    let message_height = message_lines.len() as u16;
    let button_row_height = if dialog_buttons.is_empty() { 0 } else { 3 };
    let vertical_padding = 2; // Block borders (top/bottom)
    let inner_vertical_margin = 2; // Margin inside block (top/bottom)

    // Calculate required height based on actual message lines
    let required_inner_height =
        message_height + button_row_height + inner_vertical_margin;
    let required_total_height = required_inner_height + vertical_padding;

    // Use a fixed percentage width, clamped to min/max
    let width_percentage: u16 = 60;
    let dialog_width = (area.width * width_percentage / 100)
        .max(20) // Minimum width
        .min(area.width); // Maximum width

    // Ensure height doesn't exceed available area
    let dialog_height = required_total_height.min(area.height);

    // Calculate centered area manually
    let dialog_x = area.x + (area.width.saturating_sub(dialog_width)) / 2;
    let dialog_y = area.y + (area.height.saturating_sub(dialog_height)) / 2;
    let dialog_area = Rect::new(dialog_x, dialog_y, dialog_width, dialog_height);

    // Clear the area first before drawing the dialog
    f.render_widget(Clear, dialog_area);

    let block = Block::default()
        .borders(Borders::ALL)
        .border_type(BorderType::Rounded)
        .border_style(Style::default().fg(theme.accent))
        .title(format!(" {} ", dialog_title)) // Add padding to title
        .style(Style::default().bg(theme.bg));

    f.render_widget(block, dialog_area);

    // Calculate inner area *after* defining the block
    let inner_area = dialog_area.inner(Margin {
        horizontal: 2, // Left/Right padding inside border
        vertical: 1,   // Top/Bottom padding inside border
    });

    if is_loading {
        // --- Loading State ---
        let loading_text = Paragraph::new(dialog_message) // Use the message passed for loading
            .style(Style::default().fg(theme.fg).add_modifier(Modifier::ITALIC))
            .alignment(Alignment::Center);
        // Render loading message centered in the inner area
        f.render_widget(loading_text, inner_area);
    } else {
        // --- Normal State (Message + Buttons) ---

        // Layout for Message and Buttons based on actual message height
        let mut constraints = vec![
            // Allocate space for message, ensuring at least 1 line height
            Constraint::Length(message_height.max(1)), // Use actual calculated height
        ];
        if button_row_height > 0 {
            constraints.push(Constraint::Length(button_row_height));
        }

        let chunks = Layout::default()
            .direction(Direction::Vertical)
            .constraints(constraints)
            .split(inner_area);

        // Render Message
        let available_width = inner_area.width as usize;
        let ellipsis = "...";
        let ellipsis_width = UnicodeWidthStr::width(ellipsis);

        let processed_lines: Vec<Line> = message_lines
            .into_iter()
            .map(|line| {
                let line_width = UnicodeWidthStr::width(line);
                if line_width > available_width {
                    // Truncate with ellipsis
                    let mut truncated_len = 0;
                    let mut current_width = 0;
                    for (idx, grapheme) in line.grapheme_indices(true) {
                        let grapheme_width = UnicodeWidthStr::width(grapheme);
                        if current_width + grapheme_width
                            > available_width.saturating_sub(ellipsis_width)
                        {
                            break;
                        }
                        current_width += grapheme_width;
                        truncated_len = idx + grapheme.len();
                    }
                    let truncated_line =
                        format!("{}{}", &line[..truncated_len], ellipsis);
                    Line::from(Span::styled(
                            truncated_line,
                            Style::default().fg(theme.fg),
                    ))
                } else {
                    Line::from(Span::styled(line, Style::default().fg(theme.fg)))
                }
            })
        .collect();

        let message_paragraph =
            Paragraph::new(Text::from(processed_lines)).alignment(Alignment::Center);
        f.render_widget(message_paragraph, chunks[0]); // Render message in the first chunk

        // Render Buttons if they exist and there's a chunk for them
        if !dialog_buttons.is_empty() && chunks.len() > 1 {
            let button_area = chunks[1];
            let button_count = dialog_buttons.len();

            let button_constraints = std::iter::repeat(Constraint::Ratio(
                    1,
                    button_count as u32,
            ))
                .take(button_count)
                .collect::<Vec<_>>();

            let button_chunks = Layout::default()
                .direction(Direction::Horizontal)
                .constraints(button_constraints)
                .horizontal_margin(1) // Add space between buttons
                .split(button_area);

            for (i, button_label) in dialog_buttons.iter().enumerate() {
                if i >= button_chunks.len() {
                    break;
                }

                let is_active = i == dialog_active_button_index;
                let (button_style, border_style) = if is_active {
                    (
                        Style::default()
                        .fg(theme.highlight)
                        .add_modifier(Modifier::BOLD),
                        Style::default().fg(theme.accent),
                    )
                } else {
                    (
                        Style::default().fg(theme.fg),
                        Style::default().fg(theme.border),
                    )
                };

                let button_block = Block::default()
                    .borders(Borders::ALL)
                    .border_type(BorderType::Plain)
                    .border_style(border_style);

                f.render_widget(
                    Paragraph::new(button_label.as_str())
                    .block(button_block)
                    .style(button_style)
                    .alignment(Alignment::Center),
                    button_chunks[i],
                );
            }
        }
    }
}
