use crate::{FlowLane, Rgba, ThinkingMode};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct CommandPaletteItem {
    pub title: String,
    pub detail: String,
    pub category: String,
    pub shortcut: String,
    pub keywords: Vec<String>,
}

impl CommandPaletteItem {
    pub fn matches(&self, query: &str) -> bool {
        let query = query.trim().to_ascii_lowercase();
        if query.is_empty() {
            return true;
        }
        self.title.to_ascii_lowercase().contains(&query)
            || self.detail.to_ascii_lowercase().contains(&query)
            || self.category.to_ascii_lowercase().contains(&query)
            || self
                .keywords
                .iter()
                .any(|keyword| keyword.to_ascii_lowercase().contains(&query))
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct QuickActionItem {
    pub key: Option<char>,
    pub title: String,
    pub detail: String,
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ContextItem {
    pub label: String,
    pub path_or_url: String,
    pub detail: String,
    pub selected: bool,
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ContextBucket {
    pub title: String,
    pub items: Vec<ContextItem>,
}

impl ContextBucket {
    pub fn selected_count(&self) -> usize {
        self.items.iter().filter(|item| item.selected).count()
    }
}

#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct DeckSection {
    pub lane: FlowLane,
    pub title: String,
    pub lines: Vec<String>,
    pub accent: Rgba,
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ProviderProfileView {
    pub name: String,
    pub connector: String,
    pub model: String,
    pub status: String,
    pub token_visible: bool,
}

#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ThemeEditorModel {
    pub active_theme: String,
    pub selected_field: String,
    pub selected_channel: char,
    pub preview_colors: Vec<(String, Rgba)>,
}

#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct StatusDeckModel {
    pub mode: String,
    pub thinking: ThinkingMode,
    pub provider: String,
    pub stream_enabled: bool,
    pub validation: String,
    pub sections: Vec<DeckSection>,
}

pub fn default_command_palette() -> Vec<CommandPaletteItem> {
    let items: &[(&str, &str, &str, &str, &[&str])] = &[
        (
            "Quick Actions",
            "Open fast toggles for mode, thinking, stream, context, and runtime panes",
            "control",
            "Ctrl+K",
            &["actions", "toggle", "mode"],
        ),
        (
            "Context Picker",
            "Select prompts, references, Markdown, and attachments for model context",
            "context",
            "F5",
            &["prompt", "reference", "markdown", "attach"],
        ),
        (
            "Agent Flow Cockpit",
            "Show loop lanes, Kanban, validation profiles, and run history",
            "agent",
            "F6",
            &["kanban", "loop", "runs", "validation"],
        ),
        (
            "Provider Setup",
            "Configure sidecar/provider settings without exposing secrets",
            "provider",
            "Ctrl+P",
            &["codex", "openai", "huggingface", "oauth"],
        ),
        (
            "Theme Editor",
            "Tune GPU palette fields and persist desktop visual language",
            "visual",
            "Alt+Y",
            &["shader", "palette", "glsl", "theme"],
        ),
        (
            "Run Validation",
            "Start the cheapest detected build/test/smoke command",
            "runtime",
            "Ctrl+Enter",
            &["check", "test", "build", "smoke"],
        ),
    ];

    items
        .iter()
        .map(
            |(title, detail, category, shortcut, keywords)| CommandPaletteItem {
                title: title.to_string(),
                detail: detail.to_string(),
                category: category.to_string(),
                shortcut: shortcut.to_string(),
                keywords: keywords.iter().map(|keyword| keyword.to_string()).collect(),
            },
        )
        .collect()
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn palette_search_matches_keywords() {
        let matches = default_command_palette()
            .into_iter()
            .filter(|item| item.matches("oauth"))
            .collect::<Vec<_>>();

        assert_eq!(matches.len(), 1);
        assert_eq!(matches[0].title, "Provider Setup");
    }
}
