use super::*;
use crate::key_hint;
use crate::line_truncation::truncate_line_with_ellipsis_if_overflow;
use crate::render::Insets;
use crate::render::RectExt as _;
use crate::selection_list::selection_option_row_with_dim;
use ratatui::buffer::Buffer;
use ratatui::layout::Constraint;
use ratatui::layout::Layout;
use ratatui::layout::Rect;
use ratatui::widgets::Clear;
use ratatui::widgets::Paragraph;
use ratatui::widgets::Widget;
use ratatui::widgets::WidgetRef;
use ratatui::widgets::Wrap;

impl ExternalAgentConfigMigrationScreen {
    fn render_items(&self, area: Rect, buf: &mut Buffer) {
        if area.height == 0 || area.width == 0 {
            return;
        }
        let rows = self.build_render_lines();
        let visible_rows = area.height as usize;
        let mut start_idx = self.scroll_top.min(rows.len().saturating_sub(1));
        if let Some(selected_item_idx) = self.selected_item_idx {
            let selected_render_idx = self.selected_render_line_index(selected_item_idx);
            if selected_render_idx < start_idx {
                start_idx = selected_render_idx;
            } else if visible_rows > 0 {
                let bottom = start_idx + visible_rows - 1;
                if selected_render_idx > bottom {
                    start_idx = selected_render_idx + 1 - visible_rows;
                }
            }
        }

        let mut y = area.y;
        for entry in rows.iter().skip(start_idx).take(visible_rows) {
            if y >= area.y + area.height {
                break;
            }

            let selected =
                self.focus == FocusArea::Items && self.selected_item_idx == entry.item_idx;
            let mut line = entry.line.clone();
            if selected {
                if let Some(cursor) = line.spans.first_mut() {
                    cursor.content = "› ".into();
                }
                line.spans.iter_mut().for_each(|span| {
                    span.style = span.style.cyan().bold();
                });
            } else if entry.kind != RenderLineKind::Item && !line.spans.is_empty() {
                line.spans.iter_mut().for_each(|span| {
                    span.style = span.style.dim();
                });
            }
            let line = truncate_line_with_ellipsis_if_overflow(line, area.width as usize);
            line.render(
                Rect {
                    x: area.x,
                    y,
                    width: area.width,
                    height: 1,
                },
                buf,
            );
            y = y.saturating_add(1);
        }
    }
}

impl WidgetRef for &ExternalAgentConfigMigrationScreen {
    fn render_ref(&self, area: Rect, buf: &mut Buffer) {
        Clear.render(area, buf);

        let inner_area = area.inset(Insets::vh(/*v*/ 1, /*h*/ 2));
        let error_height = u16::from(self.error.is_some());
        let intro_lines = match self.view {
            MigrationView::Summary => vec![
                Line::from("Bring over your setup, current project, and recent chats."),
                Line::from("Codex may add files to your current project folder."),
                Line::from("Your existing Claude Code setup will not be changed."),
                Line::from("Standard Claude Chat data cannot be imported."),
            ],
            MigrationView::Customize => vec![
                Line::from("Choose the Claude Code items to import."),
                Line::from("Codex may add files to your current project folder."),
                Line::from("Your existing Claude Code setup will not be changed."),
            ],
        };
        let intro_height = intro_lines.len() as u16;
        let actions = self.available_actions();
        let actions_height = actions.len() as u16 + 1;
        let fixed_height = 1u16 + intro_height + error_height + 1u16 + actions_height + 1u16;
        let list_height =
            self.render_line_count()
                .max(1)
                .min(inner_area.height.saturating_sub(fixed_height) as usize) as u16;
        let [
            header_area,
            intro_area,
            error_area,
            list_area,
            list_gap_area,
            actions_area,
            footer_area,
            _spacer_area,
        ] = Layout::vertical([
            Constraint::Length(1),
            Constraint::Length(intro_height),
            Constraint::Length(error_height),
            Constraint::Length(list_height),
            Constraint::Length(1),
            Constraint::Length(actions_height),
            Constraint::Length(1),
            Constraint::Fill(1),
        ])
        .areas(inner_area);

        let title = match self.view {
            MigrationView::Summary => "Import from Claude Code",
            MigrationView::Customize => "Choose what to import",
        };
        let heading = Line::from(vec!["> ".into(), title.bold()]);
        heading.render(header_area, buf);

        Paragraph::new(intro_lines)
            .wrap(Wrap { trim: false })
            .render(intro_area, buf);

        if let Some(error) = &self.error {
            Paragraph::new(error.clone().red().to_string())
                .wrap(Wrap { trim: false })
                .render(error_area, buf);
        }

        self.render_items(list_area, buf);
        Clear.render(list_gap_area, buf);

        let action_areas = Layout::vertical(std::iter::repeat_n(
            Constraint::Length(1),
            actions.len() + 1,
        ))
        .split(actions_area);
        let item_label = if self.items.len() == 1 {
            "item"
        } else {
            "items"
        };
        let actions_intro = format!(
            "Selected {} of {} {item_label}.",
            self.selected_count(),
            self.items.len()
        );
        Paragraph::new(actions_intro)
            .wrap(Wrap { trim: false })
            .render(action_areas[0], buf);
        for (idx, action) in actions.iter().enumerate() {
            selection_option_row_with_dim(
                idx,
                action.label().to_string(),
                self.focus == FocusArea::Actions && self.highlighted_action == *action,
                /*dim*/ self.focus != FocusArea::Actions,
            )
            .render(action_areas[idx + 1], buf);
        }

        let footer = match self.view {
            MigrationView::Summary => Line::from(vec![
                "Use ".dim(),
                key_hint::plain(KeyCode::Up).into(),
                "/".dim(),
                key_hint::plain(KeyCode::Down).into(),
                " to move, ".dim(),
                key_hint::plain(KeyCode::Enter).into(),
                " to select, ".dim(),
                "c".cyan(),
                " to customize".dim(),
            ]),
            MigrationView::Customize if self.focus == FocusArea::Actions => Line::from(vec![
                "Press ".dim(),
                key_hint::plain(KeyCode::Enter).into(),
                " to continue, ".dim(),
                key_hint::plain(KeyCode::Up).into(),
                "/".dim(),
                key_hint::plain(KeyCode::Down).into(),
                " to move, ".dim(),
                "b".cyan(),
                " to go back".dim(),
            ]),
            MigrationView::Customize => Line::from(vec![
                "Use ".dim(),
                key_hint::plain(KeyCode::Up).into(),
                "/".dim(),
                key_hint::plain(KeyCode::Down).into(),
                " to move, ".dim(),
                key_hint::plain(KeyCode::Char(' ')).into(),
                " to toggle, ".dim(),
                "b".cyan(),
                " to go back".dim(),
            ]),
        };
        footer.render(footer_area, buf);
    }
}
