//! Scrollable single-select list widget with cursor highlight.

use crate::theme;
use ratatui::layout::Rect;
use ratatui::style::{Modifier, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::Paragraph;
use ratatui::Frame;

/// Scrollable list with a highlighted cursor and selected-item marker.
pub struct ListSelect<'a> {
    items: &'a [String],
    selected: usize,
    cursor: usize,
    focused: bool,
    visible_count: usize,
    scroll_offset: usize,
}

impl<'a> ListSelect<'a> {
    pub fn new(items: &'a [String], selected: usize, cursor: usize) -> Self {
        Self {
            items,
            selected,
            cursor,
            focused: false,
            visible_count: 5,
            scroll_offset: 0,
        }
    }

    pub fn focused(mut self, focused: bool) -> Self {
        self.focused = focused;
        self
    }

    pub fn scroll_offset(mut self, offset: usize) -> Self {
        self.scroll_offset = offset;
        self
    }

    pub fn visible_count(mut self, n: usize) -> Self {
        self.visible_count = n;
        self
    }

    pub fn height(&self) -> u16 {
        let item_lines = self.items.len().min(self.visible_count) as u16;
        if self.items.len() > self.visible_count {
            item_lines + 1
        } else {
            item_lines
        }
    }

    pub fn render(self, frame: &mut Frame, area: Rect) {
        let colors = theme::get();
        let cursor_style = Style::new().fg(colors.hint.key).add_modifier(Modifier::BOLD);
        let selected_style = Style::new().fg(colors.ui.accent);
        let normal_style = Style::default();
        let indicator_style = Style::new().fg(colors.ui.text_dim);

        let visible_end = (self.scroll_offset + self.visible_count).min(self.items.len());
        let has_above = self.scroll_offset > 0;
        let has_below = visible_end < self.items.len();

        let mut lines: Vec<Line> = Vec::new();

        for i in self.scroll_offset..visible_end {
            let name = &self.items[i];
            let is_cursor = self.focused && i == self.cursor;
            let is_selected = i == self.selected;

            let style = if is_cursor {
                cursor_style
            } else if is_selected {
                selected_style
            } else {
                normal_style
            };

            let prefix = if is_selected { "x " } else { "  " };
            let mut spans = vec![
                Span::styled(prefix.to_string(), style),
                Span::styled(name.clone(), style),
            ];

            if has_above && i == self.scroll_offset {
                spans.push(Span::styled(" ▲", indicator_style));
            } else if has_below && i == visible_end - 1 {
                spans.push(Span::styled(" ▼", indicator_style));
            }

            lines.push(Line::from(spans));
        }

        if self.items.len() > self.visible_count {
            let position = self.cursor + 1;
            let total = self.items.len();
            lines.push(Line::from(Span::styled(
                format!("  ({position}/{total})"),
                indicator_style,
            )));
        }

        frame.render_widget(Paragraph::new(lines), area);
    }
}
