//! Global status bar rendering.

use crate::tui::AppState;
use crate::tui::text_edit::build_edit_value_spans;
use crate::tui::ui::theme::{self, display_width};
use ratatui::{
    Frame,
    layout::{Alignment, Constraint, Direction, Layout, Rect},
    style::{Modifier, Style},
    text::{Line, Span},
    widgets::Paragraph,
};
use std::borrow::Cow;

#[derive(Debug, Clone, Copy)]
enum StatusContext {
    HostSearch,
    TerminalSearch,
    Host,
    Terminal,
    Editor,
}

impl AppState {
    // Entry point.
    pub(crate) fn render_global_status_bar(&self, frame: &mut Frame, area: Rect) {
        if area.width == 0 || area.height == 0 {
            return;
        }

        let (left_spans, right_spans) = self.build_status_line_sections();
        let base_style = Style::default().fg(theme::ansi_white());

        if right_spans.is_empty() {
            let status = Paragraph::new(Line::from(left_spans)).style(base_style);
            frame.render_widget(status, area);
            return;
        }

        let right_width = Self::spans_display_width(&right_spans).min(area.width as usize) as u16;
        let chunks = Layout::default()
            .direction(Direction::Horizontal)
            .constraints([Constraint::Min(0), Constraint::Length(right_width)])
            .split(area);

        let left = Paragraph::new(Line::from(left_spans)).style(base_style);
        let right = Paragraph::new(Line::from(right_spans)).style(base_style).alignment(Alignment::Right);
        frame.render_widget(left, chunks[0]);
        frame.render_widget(right, chunks[1]);
    }

    // Context dispatch.
    fn build_status_line_sections(&self) -> (Vec<Span<'_>>, Vec<Span<'_>>) {
        match self.resolve_status_context() {
            StatusContext::HostSearch => self.build_search_mode_status_spans(),
            StatusContext::TerminalSearch => self.build_terminal_search_status_spans(),
            StatusContext::Host => self.build_manager_status_spans(),
            StatusContext::Terminal => self.build_terminal_status_spans(),
            StatusContext::Editor => self.build_editor_status_spans(),
        }
    }

    // Shared helpers.
    fn spans_display_width(spans: &[Span<'_>]) -> usize {
        spans.iter().map(|span| display_width(span.content.as_ref())).sum()
    }

    fn resolve_status_context(&self) -> StatusContext {
        if self.search_mode {
            return StatusContext::HostSearch;
        }
        if self.has_terminal_focus() && self.is_selected_tab_editor() {
            return StatusContext::Editor;
        }
        if self.has_terminal_focus() && self.current_tab_search().is_some_and(|search_state| search_state.active) {
            return StatusContext::TerminalSearch;
        }
        if self.has_terminal_focus() {
            return StatusContext::Terminal;
        }
        StatusContext::Host
    }

    fn has_terminal_focus(&self) -> bool {
        !self.focus_on_manager && !self.tabs.is_empty() && self.selected_tab < self.tabs.len()
    }

    // Context snippets.
    fn context_split_indicator() -> Span<'static> {
        Span::styled(" · ", Style::default().fg(theme::ansi_bright_black()))
    }

    fn selected_host_name(&self) -> Option<Cow<'_, str>> {
        if let Some(host_idx) = self.selected_host_idx() {
            return self.hosts.get(host_idx).map(|host| Cow::Borrowed(host.name.as_str()));
        }
        if let Some(folder_id) = self.selected_folder_id() {
            return self.folder_by_id(folder_id).map(|folder| Cow::Owned(format!("Folder: {}", folder.name)));
        }
        None
    }

    fn vault_status_spans(&self) -> [Span<'static>; 3] {
        let (icon, icon_color) = if self.vault_status.unlocked {
            (" ", theme::ansi_green())
        } else {
            (" ", theme::ansi_red())
        };

        [
            Span::styled(icon, Style::default().fg(icon_color).add_modifier(Modifier::BOLD)),
            Span::styled("V", Style::default().fg(theme::ansi_bright_white()).add_modifier(Modifier::UNDERLINED)),
            Span::styled("ault", Style::default().fg(theme::ansi_bright_white())),
        ]
    }

    // Host browser context.
    fn build_manager_status_spans(&self) -> (Vec<Span<'_>>, Vec<Span<'_>>) {
        let host_name = self.selected_host_name().unwrap_or(Cow::Borrowed("none"));
        let mut left = vec![
            Span::styled("Host", Style::default().fg(theme::ansi_cyan()).add_modifier(Modifier::BOLD)),
            Self::context_split_indicator(),
        ];
        left.extend(self.vault_status_spans());
        left.push(Self::context_split_indicator());
        left.push(Span::styled(host_name, Style::default().fg(theme::ansi_bright_white())));
        if !self.search_query.is_empty() {
            left.push(Self::context_split_indicator());
            left.push(Span::styled("filter:", Style::default().fg(theme::ansi_bright_black())));
            left.push(Span::styled(" ", Style::default()));
            left.push(Span::styled(self.search_query.as_str(), Style::default().fg(theme::ansi_yellow())));
            left.push(Span::styled(" ", Style::default()));
            left.push(Span::styled("(", Style::default().fg(theme::ansi_bright_black())));
            left.push(Span::styled("^C", Style::default().fg(theme::ansi_red())));
            left.push(Span::styled(")", Style::default().fg(theme::ansi_bright_black())));
        }

        let mut right = vec![
            Span::styled("n/^n", Style::default().fg(theme::ansi_yellow())),
            Span::styled(":new(host/folder) · ", Style::default().fg(theme::ansi_bright_black())),
        ];

        if self.selected_folder_id().is_some() {
            right.extend([
                Span::styled("^r", Style::default().fg(theme::ansi_cyan())),
                Span::styled(":rename · ", Style::default().fg(theme::ansi_bright_black())),
                Span::styled("^d", Style::default().fg(theme::ansi_red())),
                Span::styled(":delete · ", Style::default().fg(theme::ansi_bright_black())),
            ]);
        } else if self.selected_host_idx().is_some() {
            right.extend([
                Span::styled("e", Style::default().fg(theme::ansi_yellow())),
                Span::styled(":edit · ", Style::default().fg(theme::ansi_bright_black())),
                Span::styled("^c", Style::default().fg(theme::ansi_cyan())),
                Span::styled(":duplicate · ", Style::default().fg(theme::ansi_bright_black())),
                Span::styled("^x", Style::default().fg(theme::ansi_cyan())),
                Span::styled(":move · ", Style::default().fg(theme::ansi_bright_black())),
                Span::styled("^d", Style::default().fg(theme::ansi_red())),
                Span::styled(":delete · ", Style::default().fg(theme::ansi_bright_black())),
            ]);
        }

        right.extend([
            Span::styled("q", Style::default().fg(theme::ansi_yellow())),
            Span::styled(":quick-connect · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("↑/↓", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":move · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("^←/^→", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":resize · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("c", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":collapse · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("i", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":info · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("/", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":search · ", Style::default().fg(theme::ansi_bright_black())),
        ]);

        if !self.tabs.is_empty() {
            right.push(Span::styled(" · ", Style::default().fg(theme::ansi_bright_black())));
            right.push(Span::styled("S-Tab", Style::default().fg(theme::ansi_cyan())));
            right.push(Span::styled(":tabs", Style::default().fg(theme::ansi_bright_black())));
        }
        right.push(Span::styled("^q", Style::default().fg(theme::ansi_red())));
        right.push(Span::styled(":quit", Style::default().fg(theme::ansi_bright_black())));
        (left, right)
    }

    // Terminal context.
    fn build_terminal_status_spans(&self) -> (Vec<Span<'_>>, Vec<Span<'_>>) {
        let Some(tab) = self.selected_terminal_tab() else {
            return (
                vec![
                    Span::styled("Terminal", Style::default().fg(theme::ansi_yellow()).add_modifier(Modifier::BOLD)),
                    Span::styled(" · ", Style::default().fg(theme::ansi_bright_black())),
                    Span::styled("No active terminal", Style::default().fg(theme::ansi_bright_black())),
                ],
                Vec::new(),
            );
        };
        let is_exited = tab.session.as_ref().map(|session| session.is_exited()).unwrap_or(true);

        let status_icon_color = if is_exited { theme::ansi_red() } else { theme::ansi_green() };
        let scroll_info = if tab.scroll_offset > 0 {
            format!(" +{}", tab.scroll_offset)
        } else {
            String::new()
        };

        let mut left = vec![
            Span::styled("Terminal", Style::default().fg(theme::ansi_yellow()).add_modifier(Modifier::BOLD)),
            Self::context_split_indicator(),
            Span::styled("●", Style::default().fg(status_icon_color).add_modifier(Modifier::BOLD)),
            Span::styled(" ", Style::default()),
            Span::styled(tab.host.name.as_str(), Style::default().fg(theme::ansi_cyan()).add_modifier(Modifier::BOLD)),
        ];

        if !scroll_info.is_empty() {
            left.push(Self::context_split_indicator());
            left.push(Span::styled("sb", Style::default().fg(theme::ansi_bright_black())));
            left.push(Span::styled(scroll_info, Style::default().fg(theme::ansi_yellow())));
        }

        let mut right = Vec::new();

        if is_exited {
            right.push(Span::styled("Enter", Style::default().fg(theme::ansi_green())));
            right.push(Span::styled(":reconnect · ", Style::default().fg(theme::ansi_bright_black())));
            right.push(Span::styled("S-Tab", Style::default().fg(theme::ansi_cyan())));
            right.push(Span::styled(":mgr · ", Style::default().fg(theme::ansi_bright_black())));
            right.push(Span::styled("A-←/→", Style::default().fg(theme::ansi_cyan())));
            right.push(Span::styled(":tab · ", Style::default().fg(theme::ansi_bright_black())));
            right.push(Span::styled("^←/^→", Style::default().fg(theme::ansi_cyan())));
            right.push(Span::styled(":reorder · ", Style::default().fg(theme::ansi_bright_black())));
            right.push(Span::styled("^F", Style::default().fg(theme::ansi_cyan())));
            right.push(Span::styled(":find · ", Style::default().fg(theme::ansi_bright_black())));
            right.push(Span::styled("A-c", Style::default().fg(theme::ansi_yellow())));
            right.push(Span::styled(":copy · ", Style::default().fg(theme::ansi_bright_black())));
            right.push(Span::styled("S-PgUp/Dn", Style::default().fg(theme::ansi_yellow())));
            right.push(Span::styled(":scroll · ", Style::default().fg(theme::ansi_bright_black())));
            right.push(Span::styled("^B", Style::default().fg(theme::ansi_cyan())));
            right.push(Span::styled(":panel · ", Style::default().fg(theme::ansi_bright_black())));
            right.push(Span::styled("^W", Style::default().fg(theme::ansi_red())));
            right.push(Span::styled(":close", Style::default().fg(theme::ansi_bright_black())));
            return (left, right);
        }

        right.extend([
            Span::styled("S-Tab", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":mgr · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("A-←/→", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":tab · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("^←/^→", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":reorder · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("^F", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":find · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("A-c", Style::default().fg(theme::ansi_yellow())),
            Span::styled(":copy · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("S-PgUp/Dn", Style::default().fg(theme::ansi_yellow())),
            Span::styled(":scroll · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("^B", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":panel · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("^W", Style::default().fg(theme::ansi_red())),
            Span::styled(":close", Style::default().fg(theme::ansi_bright_black())),
        ]);

        (left, right)
    }

    fn build_editor_status_spans(&self) -> (Vec<Span<'_>>, Vec<Span<'_>>) {
        let Some(form) = self.selected_host_editor() else {
            return (
                vec![
                    Span::styled("Editor", Style::default().fg(theme::ansi_bright_cyan()).add_modifier(Modifier::BOLD)),
                    Span::styled(" · ", Style::default().fg(theme::ansi_bright_black())),
                    Span::styled("No active editor", Style::default().fg(theme::ansi_bright_black())),
                ],
                Vec::new(),
            );
        };

        let title = match form.mode {
            crate::tui::HostEditorMode::Create => "New Entry".to_string(),
            crate::tui::HostEditorMode::Edit => {
                let name = form.name.value.trim();
                if !name.is_empty() {
                    name.to_string()
                } else {
                    form.original_name.clone().unwrap_or_else(|| "Entry".to_string())
                }
            }
        };

        let left = vec![
            Span::styled("Editor", Style::default().fg(theme::ansi_bright_cyan()).add_modifier(Modifier::BOLD)),
            Self::context_split_indicator(),
            Span::styled(title, Style::default().fg(theme::ansi_bright_white())),
        ];

        let mut right = vec![
            Span::styled("Tab", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":next · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("Enter", Style::default().fg(theme::ansi_green())),
            Span::styled(":toggle/submit · ", Style::default().fg(theme::ansi_bright_black())),
        ];
        if form.mode == crate::tui::HostEditorMode::Edit {
            right.push(Span::styled("^d", Style::default().fg(theme::ansi_red())));
            right.push(Span::styled(":delete · ", Style::default().fg(theme::ansi_bright_black())));
        }
        right.push(Span::styled("Esc", Style::default().fg(theme::ansi_red())));
        right.push(Span::styled(":cancel", Style::default().fg(theme::ansi_bright_black())));

        (left, right)
    }

    // Host search context.
    fn build_search_mode_status_spans(&self) -> (Vec<Span<'_>>, Vec<Span<'_>>) {
        let cursor_style = Style::default().fg(theme::ansi_black()).bg(theme::ansi_cyan()).add_modifier(Modifier::BOLD);
        let selection_style = Style::default()
            .fg(theme::selection_fg())
            .bg(theme::selection_bg())
            .add_modifier(Modifier::BOLD);
        let mut left = vec![
            Span::styled("Host Search", Style::default().fg(theme::ansi_cyan()).add_modifier(Modifier::BOLD)),
            Self::context_split_indicator(),
        ];
        left.extend(build_edit_value_spans(
            &self.search_query,
            self.search_query_cursor,
            self.search_query_selection,
            Style::default().fg(theme::ansi_bright_white()),
            cursor_style,
            selection_style,
        ));

        let right = vec![
            Span::styled("Enter", Style::default().fg(theme::ansi_green())),
            Span::styled(":done · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("Esc", Style::default().fg(theme::ansi_red())),
            Span::styled("/", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("^C", Style::default().fg(theme::ansi_red())),
            Span::styled(":clear · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("←/→", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":move · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("Home/End", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":edge · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("^A", Style::default().fg(theme::ansi_yellow())),
            Span::styled(":all", Style::default().fg(theme::ansi_bright_black())),
        ];
        (left, right)
    }

    // Terminal search context.
    fn build_terminal_search_status_spans(&self) -> (Vec<Span<'_>>, Vec<Span<'_>>) {
        let (query, cursor, selection, matches_len, current_idx) = self.current_tab_search().map_or(("", 0usize, None, 0usize, 0usize), |search| {
            (
                search.query.as_str(),
                search.query_cursor,
                search.query_selection,
                search.matches.len(),
                search.current,
            )
        });

        let match_info = if matches_len > 0 {
            Cow::Owned(format!("{}/{}", current_idx + 1, matches_len))
        } else {
            Cow::Borrowed("0/0")
        };

        let cursor_style = Style::default().fg(theme::ansi_black()).bg(theme::ansi_cyan()).add_modifier(Modifier::BOLD);
        let selection_style = Style::default()
            .fg(theme::selection_fg())
            .bg(theme::selection_bg())
            .add_modifier(Modifier::BOLD);
        let mut left = vec![
            Span::styled("Terminal Search", Style::default().fg(theme::ansi_cyan()).add_modifier(Modifier::BOLD)),
            Self::context_split_indicator(),
        ];
        left.extend(build_edit_value_spans(
            query,
            cursor,
            selection,
            Style::default().fg(theme::ansi_bright_white()),
            cursor_style,
            selection_style,
        ));
        left.push(Span::styled(" ", Style::default()));
        left.push(Span::styled("(", Style::default().fg(theme::ansi_yellow())));
        left.push(Span::styled(match_info, Style::default().fg(theme::ansi_yellow())));
        left.push(Span::styled(")", Style::default().fg(theme::ansi_yellow())));
        let right = vec![
            Span::styled("Enter", Style::default().fg(theme::ansi_green())),
            Span::styled(":next · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("Esc", Style::default().fg(theme::ansi_red())),
            Span::styled(":clear · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("↑/↓", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":next/prev · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("←/→", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":move · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("Home/End", Style::default().fg(theme::ansi_cyan())),
            Span::styled(":edge · ", Style::default().fg(theme::ansi_bright_black())),
            Span::styled("^A", Style::default().fg(theme::ansi_yellow())),
            Span::styled(":all", Style::default().fg(theme::ansi_bright_black())),
        ];
        (left, right)
    }
}
