/* repo_view/rebase.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 gettextrs::{gettext, ngettext};
use relm4::prelude::*;

use super::branch::merge_toast_message;
use super::{RepoView, RepoViewMsg, WorkspaceTab};
use crate::git;

impl RepoView {
    pub(super) fn handle_rebase_message(
        &mut self,
        msg: RepoViewMsg,
        sender: &ComponentSender<RepoView>,
        root: &adw::ToastOverlay,
    ) {
        match msg {
            RepoViewMsg::RebaseContinue => {
                let path = self.path.clone();
                let git_command = crate::preferences::git_command();
                let has_todo = git::pending_source_ref(&path).is_some();

                sender.spawn_oneshot_command(move || {
                    if has_todo {
                        RepoViewMsg::MergeTodoComplete(git::run_todo(&path, &git_command))
                    } else {
                        RepoViewMsg::RebaseContinueComplete(git::rebase_continue(&path, &git_command))
                    }
                });
            }

            RepoViewMsg::RebaseContinueComplete(result) => match result {
                Ok(git::RebaseOutcome::Completed { commits }) => {
                    let msg = match commits {
                        Some(n) => ngettext(
                            "Rebase completed, %1 commit applied",
                            "Rebase completed, %1 commits applied",
                            n as u32,
                        )
                        .replace("%1", &n.to_string()),

                        None => gettext("Rebase completed"),
                    };

                    root.add_toast(adw::Toast::new(&msg));
                    sender.input(RepoViewMsg::Refresh);
                }

                Ok(git::RebaseOutcome::Paused { has_conflicts: true }) => {
                    root.add_toast(adw::Toast::new(&gettext("New conflicts encountered, resolve and continue")));
                    sender.input(RepoViewMsg::WorkspaceSelected(WorkspaceTab::WorkingCopy));
                    sender.input(RepoViewMsg::Refresh);
                }

                Ok(git::RebaseOutcome::Paused { has_conflicts: false }) => {
                    root.add_toast(adw::Toast::new(&gettext(
                        "Rebase paused, amend the commit, then click Continue Rebase",
                    )));
                    sender.input(RepoViewMsg::WorkspaceSelected(WorkspaceTab::WorkingCopy));
                    sender.input(RepoViewMsg::Refresh);
                }

                Err(msg) => {
                    root.add_toast(adw::Toast::new(&msg));
                }
            },

            RepoViewMsg::MergeTodoComplete(result) => {
                match result {
                    Ok(git::TodoOutcome::Done { merge, source_ref }) => {
                        root.add_toast(adw::Toast::new(&merge_toast_message(&merge, &source_ref)));
                    }

                    Ok(git::TodoOutcome::Paused { has_conflicts: true }) => {
                        root.add_toast(adw::Toast::new(&gettext("Conflicts encountered, resolve and continue")));
                        sender.input(RepoViewMsg::WorkspaceSelected(WorkspaceTab::WorkingCopy));
                    }

                    Ok(git::TodoOutcome::Paused { has_conflicts: false }) => {
                        root.add_toast(adw::Toast::new(&gettext("Merge paused, resolve and continue")));
                        sender.input(RepoViewMsg::WorkspaceSelected(WorkspaceTab::WorkingCopy));
                    }

                    Ok(git::TodoOutcome::Stuck { reason }) => {
                        root.add_toast(adw::Toast::new(&reason));
                    }

                    Ok(git::TodoOutcome::NoTodo) => {}

                    Err(msg) => {
                        root.add_toast(adw::Toast::new(&msg));
                    }
                }

                sender.input(RepoViewMsg::Refresh);
            }

            RepoViewMsg::RebaseAbort => {
                let path = self.path.clone();
                let git_command = crate::preferences::git_command();
                let was_pending_merge = git::pending_source_ref(&path).is_some();

                sender.spawn_oneshot_command(move || {
                    let result = if was_pending_merge {
                        git::abort_todo(&path, &git_command)
                    } else {
                        git::rebase_abort(&path, &git_command)
                    };

                    RepoViewMsg::RebaseAbortComplete {
                        result,
                        was_pending_merge,
                    }
                });
            }

            RepoViewMsg::RebaseAbortComplete {
                result,
                was_pending_merge,
            } => {
                match &result {
                    Ok(()) => {
                        let label = if was_pending_merge {
                            gettext("Merge aborted")
                        } else {
                            gettext("Rebase aborted")
                        };

                        root.add_toast(adw::Toast::new(&label));
                    }

                    Err(msg) => root.add_toast(adw::Toast::new(msg)),
                }

                sender.input(RepoViewMsg::Refresh);
            }

            _ => unreachable!("handle_rebase_message called with non-rebase message"),
        }
    }
}
