use adw::prelude::*;
use outlay_core::db::Database;
use std::rc::Rc;

use crate::icon_theme;

pub struct WishlistView {
    pub container: gtk::Box,
}

impl WishlistView {
    pub fn new(db: Rc<Database>) -> Self {
        let container = gtk::Box::new(gtk::Orientation::Vertical, 0);
        let toast_overlay = adw::ToastOverlay::new();

        let clamp = adw::Clamp::new();
        clamp.set_maximum_size(700);
        clamp.set_margin_start(16);
        clamp.set_margin_end(16);

        let inner = gtk::Box::new(gtk::Orientation::Vertical, 20);
        inner.set_margin_top(20);
        inner.set_margin_bottom(20);

        let total_card = gtk::Box::new(gtk::Orientation::Vertical, 4);
        total_card.add_css_class("card");
        total_card.set_margin_start(4);
        total_card.set_margin_end(4);

        let total_title = gtk::Label::new(Some("WISHLIST TOTAL"));
        total_title.add_css_class("caption");
        total_title.add_css_class("dim-label");
        total_title.set_halign(gtk::Align::Start);
        total_title.set_margin_top(12);
        total_title.set_margin_start(12);

        let base_currency = db.get_setting("base_currency")
            .ok().flatten()
            .unwrap_or_else(|| "USD".to_string());

        let total = db.get_wishlist_total().unwrap_or(0.0);
        let total_label = gtk::Label::new(Some(&format!("{:.2} {}", total, base_currency)));
        total_label.add_css_class("title-1");
        total_label.set_halign(gtk::Align::Start);
        total_label.set_margin_start(12);
        total_label.set_margin_bottom(12);

        total_card.append(&total_title);
        total_card.append(&total_label);

        let active_group = adw::PreferencesGroup::builder()
            .title("WANTED")
            .build();

        let purchased_group = adw::PreferencesGroup::builder()
            .title("PURCHASED")
            .build();

        Self::load_items(&db, &active_group, &purchased_group, &total_label, &base_currency, &toast_overlay);

        let add_btn = gtk::Button::with_label("Add Item");
        add_btn.add_css_class("suggested-action");
        add_btn.add_css_class("pill");
        add_btn.set_halign(gtk::Align::Center);
        add_btn.set_margin_top(8);

        {
            let db_ref = db.clone();
            let active_ref = active_group.clone();
            let purchased_ref = purchased_group.clone();
            let total_ref = total_label.clone();
            let currency = base_currency.clone();
            let toast_ref = toast_overlay.clone();
            add_btn.connect_clicked(move |btn| {
                Self::show_add_dialog(btn, &db_ref, &active_ref, &purchased_ref, &total_ref, &currency, &toast_ref);
            });
        }

        inner.append(&total_card);
        inner.append(&active_group);
        inner.append(&add_btn);
        inner.append(&purchased_group);

        clamp.set_child(Some(&inner));

        let scroll = gtk::ScrolledWindow::builder()
            .hscrollbar_policy(gtk::PolicyType::Never)
            .vexpand(true)
            .child(&clamp)
            .build();

        toast_overlay.set_child(Some(&scroll));
        container.append(&toast_overlay);

        WishlistView { container }
    }

    fn load_items(
        db: &Rc<Database>,
        active_group: &adw::PreferencesGroup,
        purchased_group: &adw::PreferencesGroup,
        total_label: &gtk::Label,
        base_currency: &str,
        toast_overlay: &adw::ToastOverlay,
    ) {
        Self::clear_group(active_group);
        Self::clear_group(purchased_group);

        let total = db.get_wishlist_total().unwrap_or(0.0);
        total_label.set_label(&format!("{:.2} {}", total, base_currency));

        let active = db.list_wishlist(false).unwrap_or_default();
        let purchased = db.list_wishlist(true).unwrap_or_default();

        if active.is_empty() {
            let row = adw::ActionRow::builder()
                .title("No items on your wishlist")
                .build();
            row.add_css_class("dim-label");
            active_group.add(&row);
        } else {
            for item in &active {
                let row = adw::ActionRow::builder()
                    .title(&item.name)
                    .activatable(true)
                    .build();

                if let Some(note) = &item.note {
                    if !note.is_empty() {
                        row.set_subtitle(note);
                    }
                }

                let priority_icon = match item.priority {
                    3 => Some("#e74c3c"),
                    2 => Some("#f39c12"),
                    _ => None,
                };
                if let Some(color) = priority_icon {
                    let tinted = icon_theme::get_tinted_icon_name("tabler-alert-circle", color);
                    let icon = gtk::Image::from_icon_name(&tinted);
                    icon.set_pixel_size(18);
                    row.add_prefix(&icon);
                }

                let amount_label = gtk::Label::new(Some(&format!("{:.2}", item.amount)));
                amount_label.add_css_class("amount-display");
                row.add_suffix(&amount_label);

                let item_id = item.id;
                let db_ref = db.clone();
                let active_ref = active_group.clone();
                let purchased_ref = purchased_group.clone();
                let total_ref = total_label.clone();
                let currency = base_currency.to_string();
                let toast_ref = toast_overlay.clone();
                row.connect_activated(move |row| {
                    Self::show_item_actions(row, item_id, &db_ref, &active_ref, &purchased_ref, &total_ref, &currency, &toast_ref);
                });

                active_group.add(&row);
            }
        }

        if purchased.is_empty() {
            let row = adw::ActionRow::builder()
                .title("No purchased items")
                .build();
            row.add_css_class("dim-label");
            purchased_group.add(&row);
        } else {
            for item in purchased.iter().take(10) {
                let row = adw::ActionRow::builder()
                    .title(&item.name)
                    .subtitle(&format!("{:.2}", item.amount))
                    .build();
                row.add_css_class("dim-label");
                purchased_group.add(&row);
            }
        }
    }

    fn show_add_dialog(
        parent: &gtk::Button,
        db: &Rc<Database>,
        active_group: &adw::PreferencesGroup,
        purchased_group: &adw::PreferencesGroup,
        total_label: &gtk::Label,
        base_currency: &str,
        toast_overlay: &adw::ToastOverlay,
    ) {
        let dialog = adw::Dialog::builder()
            .title("Add Wishlist Item")
            .content_width(400)
            .content_height(350)
            .build();

        let toolbar = adw::ToolbarView::new();
        toolbar.add_top_bar(&adw::HeaderBar::new());

        let content = gtk::Box::new(gtk::Orientation::Vertical, 16);
        content.set_margin_top(16);
        content.set_margin_bottom(16);
        content.set_margin_start(16);
        content.set_margin_end(16);

        let form = adw::PreferencesGroup::new();

        let name_row = adw::EntryRow::builder()
            .title("Item name")
            .build();
        form.add(&name_row);

        let amount_row = adw::EntryRow::builder()
            .title("Estimated cost")
            .build();
        amount_row.set_input_purpose(gtk::InputPurpose::Number);
        crate::numpad::attach_numpad(&amount_row);
        form.add(&amount_row);

        let priority_labels = ["Low", "Medium", "High"];
        let priority_model = gtk::StringList::new(&priority_labels);
        let priority_row = adw::ComboRow::builder()
            .title("Priority")
            .model(&priority_model)
            .selected(0)
            .build();
        form.add(&priority_row);

        let note_row = adw::EntryRow::builder()
            .title("Note (optional)")
            .build();
        form.add(&note_row);

        let url_row = adw::EntryRow::builder()
            .title("URL (optional)")
            .build();
        form.add(&url_row);

        let save_btn = gtk::Button::with_label("Save");
        save_btn.add_css_class("suggested-action");
        save_btn.add_css_class("pill");
        save_btn.set_halign(gtk::Align::Center);

        content.append(&form);
        content.append(&save_btn);
        toolbar.set_content(Some(&content));
        dialog.set_child(Some(&toolbar));

        {
            let db_ref = db.clone();
            let dialog_ref = dialog.clone();
            let active_ref = active_group.clone();
            let purchased_ref = purchased_group.clone();
            let total_ref = total_label.clone();
            let currency = base_currency.to_string();
            let toast_ref = toast_overlay.clone();
            save_btn.connect_clicked(move |_| {
                let name = name_row.text().to_string();
                if name.trim().is_empty() {
                    toast_ref.add_toast(adw::Toast::new("Please enter an item name"));
                    return;
                }

                let amount: f64 = match amount_row.text().trim().parse() {
                    Ok(v) if v > 0.0 => v,
                    _ => {
                        toast_ref.add_toast(adw::Toast::new("Please enter a valid amount"));
                        return;
                    }
                };

                let priority = match priority_row.selected() {
                    2 => 3,
                    1 => 2,
                    _ => 1,
                };

                let note_text = note_row.text();
                let note = if note_text.is_empty() { None } else { Some(note_text.as_str()) };

                let url_text = url_row.text();
                let url = if url_text.is_empty() { None } else { Some(url_text.as_str()) };

                match db_ref.insert_wishlist_item(name.trim(), amount, None, url, note, priority) {
                    Ok(_) => {
                        dialog_ref.close();
                        toast_ref.add_toast(adw::Toast::new("Item added to wishlist"));
                        Self::load_items(&db_ref, &active_ref, &purchased_ref, &total_ref, &currency, &toast_ref);
                    }
                    Err(e) => {
                        toast_ref.add_toast(adw::Toast::new(&format!("Error: {}", e)));
                    }
                }
            });
        }

        dialog.present(Some(parent));
    }

    fn show_item_actions(
        parent: &adw::ActionRow,
        item_id: i64,
        db: &Rc<Database>,
        active_group: &adw::PreferencesGroup,
        purchased_group: &adw::PreferencesGroup,
        total_label: &gtk::Label,
        base_currency: &str,
        toast_overlay: &adw::ToastOverlay,
    ) {
        let alert = adw::AlertDialog::new(
            Some("Wishlist Item"),
            Some("What would you like to do with this item?"),
        );
        alert.add_response("cancel", "Cancel");
        alert.add_response("purchased", "Mark as purchased");
        alert.add_response("delete", "Delete");
        alert.set_response_appearance("delete", adw::ResponseAppearance::Destructive);
        alert.set_default_response(Some("cancel"));
        alert.set_close_response("cancel");

        let db_ref = db.clone();
        let active_ref = active_group.clone();
        let purchased_ref = purchased_group.clone();
        let total_ref = total_label.clone();
        let currency = base_currency.to_string();
        let toast_ref = toast_overlay.clone();
        alert.connect_response(None, move |_, response| {
            match response {
                "purchased" => {
                    match db_ref.mark_wishlist_purchased(item_id) {
                        Ok(()) => {
                            toast_ref.add_toast(adw::Toast::new("Item marked as purchased"));
                            Self::load_items(&db_ref, &active_ref, &purchased_ref, &total_ref, &currency, &toast_ref);
                        }
                        Err(e) => toast_ref.add_toast(adw::Toast::new(&format!("Error: {}", e))),
                    }
                }
                "delete" => {
                    match db_ref.delete_wishlist_item(item_id) {
                        Ok(()) => {
                            toast_ref.add_toast(adw::Toast::new("Item deleted"));
                            Self::load_items(&db_ref, &active_ref, &purchased_ref, &total_ref, &currency, &toast_ref);
                        }
                        Err(e) => toast_ref.add_toast(adw::Toast::new(&format!("Error: {}", e))),
                    }
                }
                _ => {}
            }
        });

        alert.present(Some(parent));
    }

    fn clear_group(group: &adw::PreferencesGroup) {
        let mut rows = Vec::new();
        Self::collect_action_rows(group.upcast_ref(), &mut rows);
        for row in &rows {
            group.remove(row);
        }
    }

    fn collect_action_rows(widget: &gtk::Widget, rows: &mut Vec<adw::ActionRow>) {
        if let Some(row) = widget.downcast_ref::<adw::ActionRow>() {
            rows.push(row.clone());
            return;
        }
        let mut child = widget.first_child();
        while let Some(c) = child {
            Self::collect_action_rows(&c, rows);
            child = c.next_sibling();
        }
    }
}
