use ratatui::{
    Frame,
    layout::{Constraint, Direction, Layout},
    style::{Color, Modifier, Style},
    text::{Line, Span},
    widgets::{Block, Borders, List, ListItem},
};

use crossterm::event::KeyCode;

use crate::core::Result;
use crate::core::provider::Provider;
use crate::core::store::Store;

/// The provider list and selection screen state.
pub struct ListScreen {
    /// All available providers from the vault.
    pub providers: Vec<Provider>,
    /// Index of the currently selected item.
    pub selected: usize,
    /// The active filter string for searching providers.
    pub filter: String,
    /// Mapping from agent name to active provider name.
    pub state: std::collections::HashMap<String, Option<String>>,
    /// An optional status message shown in the status bar.
    pub status: Option<String>,
}

impl ListScreen {
    /// Loads all providers and state from the vault into a new ListScreen.
    pub fn load(store: &Store) -> Result<Self> {
        let store_data = store.load()?;
        let state = store.load_state()?;
        Ok(Self {
            providers: store_data.providers,
            selected: 0,
            filter: String::new(),
            state,
            status: None,
        })
    }

    /// Returns a filtered list of providers matching the current filter string.
    pub fn filtered(&self) -> Vec<&Provider> {
        self.providers
            .iter()
            .filter(|p| {
                if self.filter.is_empty() {
                    true
                } else {
                    p.name()
                        .to_lowercase()
                        .contains(&self.filter.to_lowercase())
                }
            })
            .collect()
    }

    /// Moves the selection cursor down by one item.
    pub fn move_down(&mut self) {
        let count = self.filtered().len();
        if count > 0 && self.selected + 1 < count {
            self.selected += 1;
        }
    }

    /// Moves the selection cursor up by one item.
    pub fn move_up(&mut self) {
        if self.selected > 0 {
            self.selected -= 1;
        }
    }
}

/// Handles a key event while the list screen is active.
/// Returns `Some(true)` if the app should quit, `None` otherwise.
pub fn handle_event(
    screen: &mut ListScreen,
    key: KeyCode,
    filter_mode: &mut bool,
    store: &Store,
) -> Option<bool> {
    if *filter_mode {
        match key {
            KeyCode::Char(c) => screen.filter.push(c),
            KeyCode::Backspace => {
                screen.filter.pop();
            }
            KeyCode::Esc => {
                *filter_mode = false;
                screen.filter.clear();
            }
            KeyCode::Enter => {
                *filter_mode = false;
            }
            _ => {}
        }
    } else {
        match key {
            KeyCode::Char('q') => return Some(true),
            KeyCode::Char('j') | KeyCode::Down => screen.move_down(),
            KeyCode::Char('k') | KeyCode::Up => screen.move_up(),
            KeyCode::Char('/') => *filter_mode = true,
            KeyCode::Char('s') | KeyCode::Enter => {
                let selected_info = {
                    let filtered = screen.filtered();
                    filtered
                        .get(screen.selected)
                        .map(|p| (p.name().to_string(), p.target().to_string()))
                };
                if let Some((name, target)) = selected_info {
                    let provider_opt = screen
                        .providers
                        .iter()
                        .find(|p| p.name() == name && p.target() == target)
                        .cloned();
                    if let Some(provider) = provider_opt {
                        // Apply the provider to the agent config
                        use crate::core::agent::{Agent, ClaudeCodeAdapter, CodexAdapter};
                        use std::path::PathBuf;
                        let result = match provider.target() {
                            "claude-code" => {
                                let config_path = dirs::home_dir()
                                    .unwrap_or_else(|| PathBuf::from("."))
                                    .join(".claude")
                                    .join("settings.json");
                                ClaudeCodeAdapter::new(&config_path).apply(&provider)
                            }
                            "codex" => {
                                let home = dirs::home_dir().unwrap_or_else(|| PathBuf::from("."));
                                CodexAdapter::new(
                                    &home.join(".codex").join("config.toml"),
                                    &home.join(".codex").join("auth.json"),
                                )
                                .apply(&provider)
                            }
                            _ => Ok(()),
                        };
                        match result {
                            Ok(()) => {
                                if let Ok(new_state) = store.load_state() {
                                    screen.state = new_state;
                                }
                                screen.status = Some(format!("已切换到 {} | 端点信号良好", name));
                            }
                            Err(e) => {
                                screen.status = Some(format!("切换失败: {}", e));
                            }
                        }
                        let mut state = store.load_state().unwrap_or_default();
                        state.insert(target, Some(name));
                        let _ = store.save_state(&state);
                    }
                }
            }
            _ => {}
        }
    }
    None
}

/// Draws the provider list screen with navigation, filter, and status bar.
pub fn draw(frame: &mut Frame, screen: &ListScreen) {
    let area = frame.area();
    let chunks = Layout::default()
        .direction(Direction::Vertical)
        .constraints([
            Constraint::Min(0),
            Constraint::Length(1),
            Constraint::Length(1),
        ])
        .split(area);

    let main = chunks[0];
    let status_bar = chunks[1];
    let footer = chunks[2];

    let filtered = screen.filtered();
    let items: Vec<ListItem> = filtered
        .iter()
        .enumerate()
        .map(|(i, p)| {
            let is_active = screen
                .state
                .get(p.target())
                .cloned()
                .flatten()
                .map(|n| n == p.name())
                .unwrap_or(false);

            let mut spans = vec![
                Span::raw(format!("[{}] ", p.target())),
                Span::styled(
                    p.name(),
                    if is_active {
                        Style::default()
                            .fg(Color::Rgb(0xE0, 0x40, 0x40))
                            .add_modifier(Modifier::BOLD)
                    } else {
                        Style::default()
                    },
                ),
            ];
            if is_active {
                spans.push(Span::styled(
                    " (*)",
                    Style::default().fg(Color::Rgb(0xD4, 0xA0, 0x17)),
                ));
            }

            let style = if i == screen.selected {
                Style::default().bg(Color::DarkGray)
            } else {
                Style::default()
            };

            ListItem::new(Line::from(spans)).style(style)
        })
        .collect();

    let list = List::new(items).block(
        Block::default()
            .title("罗德岛工程部 · 接入管理")
            .borders(Borders::ALL),
    );
    frame.render_widget(list, main);

    // Status bar: show last action result
    let status_text = if let Some(ref msg) = screen.status {
        Line::from(Span::styled(
            msg.clone(),
            Style::default().fg(Color::Rgb(0xD4, 0xA0, 0x17)),
        ))
    } else if screen.filter.is_empty() {
        Line::from(Span::styled(
            " / 搜索  |  j/k 移动  |  Enter/s 切换  |  q 退出",
            Style::default().fg(Color::DarkGray),
        ))
    } else {
        Line::from(Span::styled(
            format!(" 搜索: {}  |  Esc 清除  |  Enter 确认", screen.filter),
            Style::default().fg(Color::Rgb(0xD4, 0xA0, 0x17)),
        ))
    };
    frame.render_widget(status_text, status_bar);

    let footer_text = Line::from(Span::styled(
        " Closure v0.1  |  可露希尔 · 罗德岛总工程师",
        Style::default().fg(Color::DarkGray),
    ));
    frame.render_widget(footer_text, footer);
}
