/* working_copy_view/discard.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 adw::prelude::*;
use gettextrs::gettext;
use relm4::gtk;
use relm4::prelude::*;

use super::{RowSection, WorkingCopyView, WorkingCopyViewMsg};
use crate::confirm_dialog::{ConfirmDialog, ConfirmDialogInit, ConfirmDialogOutput};
use crate::git::{self, FileStatus};

#[derive(Debug)]
pub enum DiscardAction {
    Requested {
        section: RowSection,
        idx: usize,
    },
    Confirmed {
        ops: Vec<(String, Option<FileStatus>)>,
    },
    Complete {
        result: Result<(), String>,
        paths: Vec<String>,
    },
}

impl WorkingCopyView {
    pub(super) fn handle_discard_action(
        &mut self,
        action: DiscardAction,
        sender: &ComponentSender<Self>,
        root: &gtk::Box,
    ) {
        match action {
            DiscardAction::Requested { section, idx } => {
                let indices = self.expand_to_selection(section, idx);
                let ops = self.collect_ops(section, &indices);

                if ops.is_empty() {
                    return;
                }

                let window = root.ancestor(gtk::Window::static_type()).and_downcast::<gtk::Window>();

                let (heading, body) = if ops.len() == 1 {
                    (
                        gettext("Discard Changes?"),
                        gettext("Changes to “{}” will be permanently lost.").replace("{}", &ops[0].0),
                    )
                } else {
                    (
                        gettext("Discard Changes?"),
                        gettext("Changes to {} files will be permanently lost.").replace("{}", &ops.len().to_string()),
                    )
                };

                let ops_for_dialog = ops.clone();

                self.confirm_dialog = Some(
                    ConfirmDialog::builder()
                        .launch(ConfirmDialogInit {
                            heading,
                            body,
                            action_label: gettext("Discard"),
                            appearance: adw::ResponseAppearance::Destructive,
                            parent_window: window,
                        })
                        .forward(sender.input_sender(), move |output| match output {
                            ConfirmDialogOutput::Confirmed => WorkingCopyViewMsg::Discard(DiscardAction::Confirmed {
                                ops: ops_for_dialog.clone(),
                            }),

                            ConfirmDialogOutput::Cancelled => WorkingCopyViewMsg::ConfirmDialogDismissed,
                        }),
                );
            }

            DiscardAction::Confirmed { ops } => {
                self.confirm_dialog = None;
                let repo_path = self.path.clone();
                let paths: Vec<String> = ops.iter().map(|(p, _)| p.clone()).collect();

                sender.spawn_oneshot_command(move || {
                    let result = git::discard_files(&repo_path, &ops);
                    WorkingCopyViewMsg::Discard(DiscardAction::Complete { result, paths })
                });
            }

            DiscardAction::Complete { result, paths } => {
                self.handle_operation_complete(&result, sender, paths);
            }
        }
    }
}
