/* commit_log_view/search.rs
 *
 * Copyright 2026 Christian Kruse
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

use std::path::PathBuf;

use relm4::prelude::*;

use super::{CommitItem, CommitLogView, CommitLogViewMsg, CommitLogViewOutput};
use crate::commit_search_bar::{CommitSearchBar, CommitSearchBarMsg, CommitSearchBarOutput};
use crate::git::CommitInfo;

#[derive(Debug)]
pub enum SearchAction {
    ToggleSearch,
    CancelSearch,
    SearchResultBatch(Vec<CommitInfo>),
    SearchStarted,
    SearchComplete,
    SearchCleared,
}

impl CommitLogView {
    pub(super) fn build_search_bar(path: PathBuf, sender: &ComponentSender<Self>) -> Controller<CommitSearchBar> {
        CommitSearchBar::builder()
            .launch(path)
            .forward(sender.input_sender(), |output| match output {
                CommitSearchBarOutput::SearchStarted => CommitLogViewMsg::Search(SearchAction::SearchStarted),
                CommitSearchBarOutput::SearchComplete => CommitLogViewMsg::Search(SearchAction::SearchComplete),
                CommitSearchBarOutput::Cleared => CommitLogViewMsg::Search(SearchAction::SearchCleared),
                CommitSearchBarOutput::ShowToast(msg) => CommitLogViewMsg::ShowToast(msg),

                CommitSearchBarOutput::ResultBatch(commits) => {
                    CommitLogViewMsg::Search(SearchAction::SearchResultBatch(commits))
                }
            })
    }

    pub(super) fn handle_search_action(
        &mut self,
        action: SearchAction,
        widgets: &mut <Self as Component>::Widgets,
        sender: &ComponentSender<Self>,
    ) {
        match action {
            SearchAction::ToggleSearch => {
                self.search_bar.emit(CommitSearchBarMsg::Toggle);
            }

            SearchAction::CancelSearch => {
                self.search_bar.emit(CommitSearchBarMsg::Cancel);
            }

            SearchAction::SearchResultBatch(commits) => {
                self.list_view
                    .extend_from_iter(commits.into_iter().map(|commit| CommitItem {
                        commit,
                        tags: Vec::new(),
                        upstream_name: None,
                        local_branches: Vec::new(),
                        remote_branches: Vec::new(),
                    }));
            }

            SearchAction::SearchStarted => {
                self.list_view.clear();
                self.selected_oid = None;
                self.diff_factory.guard().clear();
                widgets.detail_stack.set_visible_child_name("empty");
                sender.output(CommitLogViewOutput::SelectedCommitChanged(None)).ok();
            }

            SearchAction::SearchComplete => {}

            SearchAction::SearchCleared => {
                if let Some(ref_name) = self.current_ref.clone() {
                    self.start_load(widgets, &ref_name, sender);
                }
            }
        }
    }
}
