use adw::prelude::*;
use std::cell::RefCell;
use std::rc::Rc;

use crate::core::database::Database;
use crate::core::duplicates::{self, DuplicateGroup, MatchReason, MemberRecommendation};
use crate::core::integrator;
use crate::i18n::{i18n, i18n_f, ni18n_f};
use super::widgets;

/// Show a dialog listing duplicate/multi-version AppImages with resolution options.
pub fn show_duplicate_dialog(
    parent: &impl IsA<gtk::Widget>,
    db: &Rc<Database>,
    toast_overlay: &adw::ToastOverlay,
) {
    let groups = duplicates::detect_duplicates(db);

    if groups.is_empty() {
        let dialog = adw::AlertDialog::builder()
            .heading(&i18n("No Duplicates Found"))
            .body(&i18n("No duplicate or multi-version AppImages were detected."))
            .build();
        dialog.add_response("ok", &i18n("OK"));
        dialog.set_default_response(Some("ok"));
        dialog.present(Some(parent));
        return;
    }

    let summary = duplicates::summarize_duplicates(&groups);

    let dialog = adw::Dialog::builder()
        .title(&i18n("Duplicates & Old Versions"))
        .content_width(600)
        .content_height(500)
        .build();

    let toolbar = adw::ToolbarView::new();
    let header = adw::HeaderBar::new();

    // "Remove All Suggested" bulk action button
    let bulk_btn = gtk::Button::builder()
        .label(&i18n("Remove All Suggested"))
        .tooltip_text(&i18n("Delete all items recommended for removal"))
        .build();
    bulk_btn.add_css_class("destructive-action");
    bulk_btn.update_property(&[
        gtk::accessible::Property::Label(&i18n("Remove all suggested duplicates")),
    ]);
    header.pack_end(&bulk_btn);

    toolbar.add_top_bar(&header);

    let scrolled = gtk::ScrolledWindow::builder()
        .vexpand(true)
        .build();

    let content = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .spacing(16)
        .margin_top(16)
        .margin_bottom(16)
        .margin_start(16)
        .margin_end(16)
        .build();

    // Summary banner
    let summary_text = i18n_f(
        "{groups} groups found ({exact} exact duplicates, {multi} with multiple versions). Potential savings: {savings}",
        &[
            ("{groups}", &summary.total_groups.to_string()),
            ("{exact}", &summary.exact_duplicates.to_string()),
            ("{multi}", &summary.multi_version.to_string()),
            ("{savings}", &widgets::format_size(summary.total_potential_savings as i64)),
        ],
    );
    let summary_label = gtk::Label::builder()
        .label(&summary_text)
        .wrap(true)
        .halign(gtk::Align::Start)
        .build();
    summary_label.add_css_class("dimmed");
    content.append(&summary_label);

    // Collect all removable records for bulk action
    let removable_records: Rc<RefCell<Vec<(i64, String, String, bool)>>> =
        Rc::new(RefCell::new(Vec::new()));

    // Build a PreferencesGroup for each duplicate group
    for group in &groups {
        let (group_widget, group_removable) = build_group_widget(group, db, toast_overlay);
        content.append(&group_widget);
        removable_records.borrow_mut().extend(group_removable);
    }

    // Wire bulk action with confirmation dialog
    let db_bulk = db.clone();
    let toast_bulk = toast_overlay.clone();
    let removable = removable_records;
    bulk_btn.connect_clicked(move |btn| {
        let count = removable.borrow().len();
        if count == 0 {
            return;
        }

        let confirm = adw::AlertDialog::builder()
            .heading(&i18n("Confirm Removal"))
            .body(&ni18n_f(
                "Remove {count} suggested duplicate?",
                "Remove {count} suggested duplicates?",
                count as u32,
                &[("{count}", &count.to_string())],
            ))
            .build();
        confirm.add_response("cancel", &i18n("Cancel"));
        confirm.add_response("remove", &i18n("Remove"));
        confirm.set_response_appearance("remove", adw::ResponseAppearance::Destructive);
        confirm.set_default_response(Some("cancel"));
        confirm.set_close_response("cancel");

        let db_confirm = db_bulk.clone();
        let toast_confirm = toast_bulk.clone();
        let removable_confirm = removable.clone();
        let btn_ref = btn.clone();

        confirm.connect_response(None, move |_dlg, response| {
            if response != "remove" {
                return;
            }
            let records = removable_confirm.borrow();
            let mut removed_count = 0;
            for (record_id, record_path, _record_name, integrated) in records.iter() {
                if *integrated {
                    integrator::undo_all_modifications(&db_confirm, *record_id).ok();
                    if let Ok(Some(full_record)) = db_confirm.get_appimage_by_id(*record_id) {
                        integrator::remove_integration(&full_record).ok();
                    }
                    db_confirm.set_integrated(*record_id, false, None).ok();
                }
                std::fs::remove_file(record_path).ok();
                db_confirm.remove_appimage(*record_id).ok();
                removed_count += 1;
            }
            if removed_count > 0 {
                toast_confirm.add_toast(widgets::info_toast(&ni18n_f(
                    "Removed {count} item",
                    "Removed {count} items",
                    removed_count as u32,
                    &[("{count}", &removed_count.to_string())],
                )));
                btn_ref.set_sensitive(false);
                btn_ref.set_label(&i18n("Done"));
            }
        });

        confirm.present(Some(btn));
    });

    scrolled.set_child(Some(&content));
    toolbar.set_content(Some(&scrolled));
    dialog.set_child(Some(&toolbar));

    dialog.present(Some(parent));
}

fn build_group_widget(
    group: &DuplicateGroup,
    db: &Rc<Database>,
    toast_overlay: &adw::ToastOverlay,
) -> (adw::PreferencesGroup, Vec<(i64, String, String, bool)>) {
    let reason_text = match group.match_reason {
        MatchReason::ExactDuplicate => i18n("Exact duplicate"),
        MatchReason::MultiVersion => i18n("Multiple versions"),
        MatchReason::SameVersionDifferentPath => i18n("Same version, different path"),
    };

    let description = if group.potential_savings > 0 {
        i18n_f(
            "{reason} - Total: {total} - Potential savings: {savings}",
            &[
                ("{reason}", &reason_text),
                ("{total}", &widgets::format_size(group.total_size as i64)),
                ("{savings}", &widgets::format_size(group.potential_savings as i64)),
            ],
        )
    } else {
        i18n_f(
            "{reason} - Total: {total}",
            &[
                ("{reason}", &reason_text),
                ("{total}", &widgets::format_size(group.total_size as i64)),
            ],
        )
    };

    let pref_group = adw::PreferencesGroup::builder()
        .title(&group.app_name)
        .description(&description)
        .build();

    let mut removable = Vec::new();

    for member in &group.members {
        let record = &member.record;
        let unknown = i18n("unknown");
        let version = record.app_version.as_deref().unwrap_or(&unknown);
        let size = widgets::format_size(record.size_bytes);

        let title = if member.is_recommended {
            i18n_f("{version} ({size}) - Recommended", &[("{version}", version), ("{size}", &size)])
        } else {
            format!("{} ({})", version, size)
        };
        let row = adw::ActionRow::builder()
            .title(&title)
            .subtitle(&record.path)
            .build();

        // Recommendation badge
        let badge_class = match member.recommendation {
            MemberRecommendation::KeepNewest | MemberRecommendation::KeepIntegrated => "success",
            MemberRecommendation::RemoveOlder | MemberRecommendation::RemoveDuplicate => "error",
            MemberRecommendation::UserChoice => "neutral",
        };
        let badge = widgets::status_badge(member.recommendation.label(), badge_class);
        badge.set_valign(gtk::Align::Center);
        row.add_suffix(&badge);

        // Add delete button for removable members
        let is_removable = matches!(
            member.recommendation,
            MemberRecommendation::RemoveOlder | MemberRecommendation::RemoveDuplicate
        );
        if is_removable {
            removable.push((
                record.id,
                record.path.clone(),
                record.app_name.clone().unwrap_or_else(|| record.filename.clone()),
                record.integrated,
            ));

            let delete_btn = gtk::Button::builder()
                .icon_name("user-trash-symbolic")
                .tooltip_text(&i18n("Delete this AppImage"))
                .css_classes(["flat", "circular"])
                .valign(gtk::Align::Center)
                .build();
            delete_btn.add_css_class("destructive-action");

            let record_id = record.id;
            let record_path = record.path.clone();
            let record_name = record.app_name.clone().unwrap_or_else(|| record.filename.clone());
            delete_btn.update_property(&[
                gtk::accessible::Property::Label(&i18n_f("Delete {name}", &[("{name}", &record_name)])),
            ]);
            let db_ref = db.clone();
            let toast_ref = toast_overlay.clone();
            let record_clone = record.clone();

            delete_btn.connect_clicked(move |btn| {
                // Remove integration if any
                if record_clone.integrated {
                    integrator::undo_all_modifications(&db_ref, record_id).ok();
                    integrator::remove_integration(&record_clone).ok();
                    db_ref.set_integrated(record_id, false, None).ok();
                }
                // Delete the AppImage file
                std::fs::remove_file(&record_path).ok();
                // Remove from database
                db_ref.remove_appimage(record_id).ok();
                // Update UI
                btn.set_sensitive(false);
                toast_ref.add_toast(widgets::info_toast(&i18n_f("Removed {name}", &[("{name}", &record_name)])));
            });

            row.add_suffix(&delete_btn);
        }

        pref_group.add(&row);
    }

    (pref_group, removable)
}
