use crate::client::tui::app::{App, ConfirmAction, Focus, Modal};
use crate::client::tui::components::*;
use ratatui::{
    Frame,
    layout::{Constraint, Direction, Layout, Rect},
    style::{Color, Modifier, Style},
    text::{Line, Span},
    widgets::{Block, Borders, Clear, Paragraph, Wrap},
};
use unicode_width::UnicodeWidthStr;

pub fn render_ui(frame: &mut Frame, app: &App) {
    let area = frame.area();
    let input_height = app.input.lines().count().clamp(1, 6) as u16 + 2;
    let rows = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Length(3),
            Constraint::Min(3),
            Constraint::Length(input_height),
            Constraint::Length(1),
        ])
        .split(area);

    title_bar::render(frame, rows[0], app);
    if area.width >= 80 {
        let columns = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([Constraint::Length(28), Constraint::Min(30)])
            .split(rows[1]);
        session_list::render(frame, columns[0], app);
        chat_history::render(frame, columns[1], app);
    } else {
        chat_history::render(frame, rows[1], app);
    }
    input_area::render(frame, rows[2], app);
    render_footer(frame, rows[3], app);

    if app.show_command_menu && !app.get_filtered_commands().is_empty() {
        let height = (app.get_filtered_commands().len().min(6) + 2) as u16;
        let menu_area = Rect::new(
            rows[2].x.saturating_add(1),
            rows[2].y.saturating_sub(height),
            rows[2].width.saturating_sub(2),
            height,
        );
        command_menu::render(frame, menu_area, app);
    }
    if app.show_help {
        help_popup::render(frame, centered_rect(72, 26, area));
    }
    if let Some(modal) = &app.modal {
        render_modal(frame, centered_rect(64, 7, area), modal);
    }
}

fn render_footer(frame: &mut Frame, area: Rect, app: &App) {
    let focus = match app.focus {
        Focus::Input => "输入",
        Focus::Sessions => "会话",
    };
    let status =
        app.status_message
            .as_deref()
            .unwrap_or(if app.connected { "就绪" } else { "已断开" });
    let line = Line::from(vec![
        Span::styled(
            format!(" {focus} "),
            Style::default().fg(Color::Black).bg(Color::Cyan),
        ),
        Span::raw(format!(" {status}")),
        Span::styled(
            "   F1 帮助  Tab 切换焦点  Ctrl+N 新会话 ",
            Style::default().fg(Color::DarkGray),
        ),
    ]);
    frame.render_widget(Paragraph::new(line), area);
}

fn render_modal(frame: &mut Frame, area: Rect, modal: &Modal) {
    frame.render_widget(Clear, area);
    let block = Block::default()
        .borders(Borders::ALL)
        .border_style(Style::default().fg(Color::Yellow));
    match modal {
        Modal::Rename { input, cursor } => {
            frame.render_widget(
                Paragraph::new(vec![
                    Line::from(Span::styled(
                        "重命名会话",
                        Style::default().add_modifier(Modifier::BOLD),
                    )),
                    Line::from(""),
                    Line::from(input.as_str()),
                    Line::from(Span::styled(
                        "Enter 保存 · Esc 取消",
                        Style::default().fg(Color::DarkGray),
                    )),
                ])
                .block(block)
                .wrap(Wrap { trim: false }),
                area,
            );
            let cursor_x = area.x
                + 1
                + UnicodeWidthStr::width(&input[..*cursor])
                    .min(area.width.saturating_sub(3) as usize) as u16;
            let cursor_y = area.y.saturating_add(3);
            if cursor_x < area.right() && cursor_y < area.bottom() {
                frame.set_cursor_position((cursor_x, cursor_y));
            }
        }
        Modal::AttachPath { input, cursor } => {
            frame.render_widget(
                Paragraph::new(vec![
                    Line::from(Span::styled(
                        "添加附件路径",
                        Style::default().add_modifier(Modifier::BOLD),
                    )),
                    Line::from(""),
                    Line::from(input.as_str()),
                    Line::from(Span::styled(
                        "Enter 上传 · Esc 取消",
                        Style::default().fg(Color::DarkGray),
                    )),
                ])
                .block(block)
                .wrap(Wrap { trim: false }),
                area,
            );
            let cursor_x = area.x
                + 1
                + UnicodeWidthStr::width(&input[..*cursor])
                    .min(area.width.saturating_sub(3) as usize) as u16;
            let cursor_y = area.y.saturating_add(3);
            if cursor_x < area.right() && cursor_y < area.bottom() {
                frame.set_cursor_position((cursor_x, cursor_y));
            }
        }
        Modal::Confirm(action) => {
            let prompt = match action {
                ConfirmAction::Archive => "归档所选会话？",
                ConfirmAction::Delete => "永久删除所选会话？此操作不可撤销。",
                ConfirmAction::ClearHistory => "清空所选会话的全部历史？",
            };
            frame.render_widget(
                Paragraph::new(vec![
                    Line::from(""),
                    Line::from(prompt),
                    Line::from(""),
                    Line::from(Span::styled(
                        "Y / Enter 确认 · N / Esc 取消",
                        Style::default().fg(Color::DarkGray),
                    )),
                ])
                .block(block)
                .wrap(Wrap { trim: false }),
                area,
            );
        }
    }
}

fn centered_rect(max_width: u16, max_height: u16, area: Rect) -> Rect {
    let width = max_width.min(area.width.saturating_sub(2)).max(1);
    let height = max_height.min(area.height.saturating_sub(2)).max(1);
    Rect::new(
        area.x + area.width.saturating_sub(width) / 2,
        area.y + area.height.saturating_sub(height) / 2,
        width,
        height,
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use ratatui::{Terminal, backend::TestBackend};

    #[test]
    fn narrow_terminal_renders_without_sidebar_or_panic() {
        let backend = TestBackend::new(48, 14);
        let mut terminal = Terminal::new(backend).unwrap();
        let mut app = App::new();
        app.input_insert_str("中文 input");
        app.add_message(
            crate::client::tui::app::MessageRole::Assistant,
            "一条很长的响应，用于验证窄终端换行。".repeat(4),
        );
        terminal.draw(|frame| render_ui(frame, &app)).unwrap();
    }

    #[test]
    fn active_reasoning_text_and_tool_snapshot_renders_without_panic() {
        let backend = TestBackend::new(96, 24);
        let mut terminal = Terminal::new(backend).unwrap();
        let mut app = App::new();
        app.set_current_session(Some("session".into()));
        let (controller, emitter, _) = crate::session::TurnController::start("session", "message");
        emitter
            .emit(crate::agent::TurnEvent::ReasoningDelta {
                iteration: 0,
                delta: "先检查状态".into(),
            })
            .unwrap();
        emitter
            .emit(crate::agent::TurnEvent::TextDelta {
                iteration: 0,
                delta: "正在处理".into(),
            })
            .unwrap();
        emitter
            .emit(crate::agent::TurnEvent::ToolStarted {
                iteration: 0,
                call: crate::providers::ToolCall {
                    id: "call".into(),
                    name: "bash".into(),
                    arguments: serde_json::json!({"cmd": "pwd"}),
                },
            })
            .unwrap();
        app.apply_turn_snapshot((*controller.snapshot()).clone());

        terminal.draw(|frame| render_ui(frame, &app)).unwrap();
    }
}
