///|
/// Combobox - Dropdown with text input and autocomplete

///|
/// Combobox option
pub(all) struct ComboboxOption {
  id : String
  label : String
} derive(Eq)

///|
/// Combobox state
pub(all) enum ComboboxState {
  Closed
  Open
  Editing
  Disabled
}

///|
/// Create a combobox component with theme support
pub fn combobox(
  options : Array[ComboboxOption],
  selected_id : String,
  id? : String = "",
  focused_id? : String = "",
  state? : ComboboxState = ComboboxState::Closed,
  filter? : String = "",
  placeholder? : String = "Select...",
  theme? : Theme = Theme::default(),
  // Size
  width? : @types.Dimension = @types.Dimension::Auto,
  min_width? : Double = 15.0,
  max_visible? : Int = 5,
  // Icons
  dropdown_icon? : String = "▼",
  dropdown_icon_open? : String = "▲",
) -> @core.Component {
  // Find selected option label
  let selected_label = options.iter().find_first(fn(o) { o.id == selected_id })
    |> Option::map(fn(o) { o.label })
    |> Option::unwrap_or(placeholder)

  // Display text based on state
  let display_text = match state {
    ComboboxState::Editing => filter + "_"
    ComboboxState::Open | ComboboxState::Closed | ComboboxState::Disabled =>
      selected_label
  }

  // Border and fg color based on state
  let (actual_border, header_fg) = match state {
    ComboboxState::Open | ComboboxState::Editing => (theme.focus, theme.fg)
    ComboboxState::Disabled => (theme.disabled, theme.disabled)
    _ => (theme.border, theme.fg)
  }

  // Icon based on state
  let icon = match state {
    ComboboxState::Open | ComboboxState::Editing => dropdown_icon_open
    _ => dropdown_icon
  }

  // Build header (input field with dropdown icon)
  let header = row(
    [text(display_text, fg=header_fg), spacer(), text(icon, fg=theme.muted)],
    id=id + "-header",
    width~,
    min_width=@types.Dimension::Length(min_width),
    padding_x=1.0,
    border=Some(@core.BorderChars::rounded()),
    border_color=actual_border,
  )

  // Build dropdown list if open
  match state {
    ComboboxState::Open | ComboboxState::Editing => {
      // Filter options based on input
      let filtered = if filter.length() > 0 {
        options
        .iter()
        .filter(fn(o) { o.label.to_lower().contains(filter.to_lower()) })
        |> Iter::collect
      } else {
        options
      }

      // Limit visible options
      let visible_count = if filtered.length() > max_visible {
        max_visible
      } else {
        filtered.length()
      }
      let option_items : Array[@core.Component] = []
      for i = 0; i < visible_count; i = i + 1 {
        let opt = filtered[i]
        let is_selected = opt.id == selected_id
        let is_focused = opt.id == focused_id
        let opt_fg = if is_focused {
          theme.focus
        } else if is_selected {
          theme.primary
        } else {
          theme.fg
        }
        let prefix = if is_focused {
          "▸ "
        } else if is_selected {
          "● "
        } else {
          "  "
        }
        option_items.push(
          row([text(prefix + opt.label, fg=opt_fg)], id=opt.id, padding_x=1.0),
        )
      }

      // Show "no results" if filter matches nothing
      if option_items.is_empty() {
        option_items.push(
          row([text("No matches", fg=theme.disabled)], padding_x=1.0),
        )
      }

      // Add scroll indicator if more items
      if filtered.length() > max_visible {
        option_items.push(
          row(
            [
              text(
                "... " + (filtered.length() - max_visible).to_string() + " more",
                fg=theme.disabled,
              ),
            ],
            padding_x=1.0,
          ),
        )
      }
      let dropdown = column(
        option_items,
        id=id + "-dropdown",
        width~,
        min_width=@types.Dimension::Length(min_width),
        border=Some(@core.BorderChars::rounded()),
        border_color=actual_border,
      )
      column([header, dropdown], id~)
    }
    _ => column([header], id~)
  }
}

///|
/// Simple select dropdown (no text input) with theme support
pub fn select(
  options : Array[ComboboxOption],
  selected_id : String,
  id? : String = "",
  focused_id? : String = "",
  open? : Bool = false,
  placeholder? : String = "Select...",
  theme? : Theme = Theme::default(),
  // Size
  min_width? : Double = 15.0,
  max_visible? : Int = 5,
) -> @core.Component {
  let state = if open { ComboboxState::Open } else { ComboboxState::Closed }
  combobox(
    options,
    selected_id,
    id~,
    focused_id~,
    state~,
    placeholder~,
    theme~,
    min_width~,
    max_visible~,
  )
}

///|
/// Autocomplete input (text input with suggestions) with theme support
pub fn autocomplete(
  options : Array[ComboboxOption],
  value : String,
  id? : String = "",
  focused_id? : String = "",
  placeholder? : String = "Type to search...",
  theme? : Theme = Theme::default(),
  // Size
  min_width? : Double = 20.0,
  max_visible? : Int = 5,
) -> @core.Component {
  let state = if value.length() > 0 {
    ComboboxState::Editing
  } else {
    ComboboxState::Closed
  }
  combobox(
    options,
    "",
    id~,
    focused_id~,
    state~,
    filter=value,
    placeholder~,
    theme~,
    min_width~,
    max_visible~,
  )
}