//! Right-pane tab implementations.
//!
//! Each tab is a small self-contained module so the per-tab state
//! and render code stays close together. The [`RightTab`] enum is
//! the single shared identifier; `tabs_for_mode` resolves the set
//! of tabs reachable for a given model mode hint.

pub mod chat;
pub mod embed;
pub mod input_pane;
pub mod logs;
pub mod rerank;
pub mod settings;

use crate::gguf::metadata::ModeHint;

/// Identifier for one right-pane tab. `Settings` is always
/// reachable; the mode-specific tabs become reachable when the
/// focused model is `Ready` and its `ModeHint` matches. Variant
/// order matches the user-facing tab strip: Settings is the
/// canonical first stop, Logs follows, then the mode tab.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RightTab {
  /// Launch-parameter form. Editable for not-yet-launched models;
  /// read-only for running models (shows the params used).
  Settings,
  Logs,
  Chat,
  Embed,
  Rerank,
}

impl RightTab {
  pub fn label(&self) -> &'static str {
    match self {
      RightTab::Settings => "Settings",
      RightTab::Logs => "Logs",
      RightTab::Chat => "Chat",
      RightTab::Embed => "Embed",
      RightTab::Rerank => "Rerank",
    }
  }
}

/// One-off events generated by async tab tasks (embed, rerank).
/// Lives here rather than in `tui::events` so per-tab modules
/// (`tabs::embed`, `tabs::rerank`) don't need to reach up into the
/// event-loop module. The chat tab streams via its own
/// `ChatStreamMsg` channel held inside `ChatTabState`; embed/rerank
/// only need a single result message so the receivers live on their
/// respective tab states.
#[derive(Debug)]
pub enum TabEvent {
  EmbedOk(crate::tui::oai_client::EmbedResult),
  EmbedErr(String),
  RerankOk(Vec<(usize, f64)>),
  RerankErr(String),
}

/// Tabs available for a model with the supplied mode hint. The
/// renderer only exposes the second tab when the model is `Ready`;
/// this helper just declares which tab type is appropriate.
pub fn tabs_for_mode(mode: ModeHint) -> Vec<RightTab> {
  // Settings leads (it's always present and the home for launch
  // params); Logs follows so a running model's process pipeline
  // is one Tab away; the mode-specific surface (Chat / Embed /
  // Rerank) trails as the third tab.
  match mode {
    ModeHint::Chat => vec![RightTab::Settings, RightTab::Logs, RightTab::Chat],
    ModeHint::Embedding => vec![RightTab::Settings, RightTab::Logs, RightTab::Embed],
    ModeHint::Rerank => vec![RightTab::Settings, RightTab::Logs, RightTab::Rerank],
    ModeHint::Unknown => vec![RightTab::Settings, RightTab::Logs],
  }
}

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

  #[test]
  fn unknown_mode_exposes_settings_and_logs() {
    assert_eq!(
      tabs_for_mode(ModeHint::Unknown),
      vec![RightTab::Settings, RightTab::Logs]
    );
  }

  #[test]
  fn chat_mode_orders_settings_logs_chat() {
    assert_eq!(
      tabs_for_mode(ModeHint::Chat),
      vec![RightTab::Settings, RightTab::Logs, RightTab::Chat]
    );
  }

  #[test]
  fn embedding_mode_orders_settings_logs_embed() {
    assert_eq!(
      tabs_for_mode(ModeHint::Embedding),
      vec![RightTab::Settings, RightTab::Logs, RightTab::Embed]
    );
  }
}
