use adw::prelude::*;
use pixstrip_core::preset::Preset;
use pixstrip_core::operations::*;
use crate::app::{AppState, JobConfig, MetadataMode};

pub fn build_workflow_page(state: &AppState) -> adw::NavigationPage {
    let scrolled = gtk::ScrolledWindow::builder()
        .hscrollbar_policy(gtk::PolicyType::Never)
        .vexpand(true)
        .build();

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

    // Built-in presets section
    let builtin_group = adw::PreferencesGroup::builder()
        .title("Built-in Workflows")
        .description("Select a preset to get started quickly")
        .build();

    let builtin_flow = gtk::FlowBox::builder()
        .selection_mode(gtk::SelectionMode::Single)
        .max_children_per_line(5)
        .min_children_per_line(2)
        .row_spacing(8)
        .column_spacing(8)
        .homogeneous(true)
        .build();

    builtin_flow.update_property(&[
        gtk::accessible::Property::Label("Workflow preset selection grid"),
    ]);

    // Custom card is always first (index 0)
    let custom_card = build_custom_card();
    builtin_flow.append(&custom_card);

    // Then all built-in presets (indices 1..=9)
    let builtins = Preset::all_builtins();
    for preset in &builtins {
        let card = build_preset_card(preset);
        builtin_flow.append(&card);
    }

    // Custom workflow section (hidden until Custom card is selected)
    let custom_group = adw::PreferencesGroup::builder()
        .title("Custom Workflow")
        .description("Choose which operations to include, then click Next")
        .visible(false)
        .build();

    let resize_check = adw::SwitchRow::builder()
        .title("Resize")
        .subtitle("Scale images to new dimensions")
        .active(state.job_config.borrow().resize_enabled)
        .build();

    let adjustments_check = adw::SwitchRow::builder()
        .title("Adjustments")
        .subtitle("Rotate, flip, brightness, contrast, effects")
        .active(state.job_config.borrow().adjustments_enabled)
        .build();

    let convert_check = adw::SwitchRow::builder()
        .title("Convert")
        .subtitle("Change image format (JPEG, PNG, WebP, AVIF)")
        .active(state.job_config.borrow().convert_enabled)
        .build();

    let compress_check = adw::SwitchRow::builder()
        .title("Compress")
        .subtitle("Reduce file size with quality control")
        .active(state.job_config.borrow().compress_enabled)
        .build();

    let metadata_check = adw::SwitchRow::builder()
        .title("Metadata")
        .subtitle("Strip or modify EXIF, GPS, camera data")
        .active(state.job_config.borrow().metadata_enabled)
        .build();

    let watermark_check = adw::SwitchRow::builder()
        .title("Watermark")
        .subtitle("Add text or image overlay")
        .active(state.job_config.borrow().watermark_enabled)
        .build();

    let rename_check = adw::SwitchRow::builder()
        .title("Rename")
        .subtitle("Rename files with prefix, suffix, or template")
        .active(state.job_config.borrow().rename_enabled)
        .build();

    custom_group.add(&resize_check);
    custom_group.add(&adjustments_check);
    custom_group.add(&convert_check);
    custom_group.add(&compress_check);
    custom_group.add(&metadata_check);
    custom_group.add(&watermark_check);
    custom_group.add(&rename_check);

    // When a card is activated: Custom shows toggles, presets apply config and advance
    {
        let jc = state.job_config.clone();
        let custom_group_c = custom_group.clone();
        builtin_flow.connect_child_activated(move |flow, child| {
            let idx = child.index() as usize;
            if idx == 0 {
                // Custom card - show toggles, don't advance, enable step-by-step mode
                jc.borrow_mut().preset_mode = false;
                custom_group_c.set_visible(true);
            } else {
                // Built-in preset - apply config, skip intermediate steps, advance
                custom_group_c.set_visible(false);
                if let Some(preset) = builtins.get(idx - 1) {
                    let mut cfg = jc.borrow_mut();
                    apply_preset_to_config(&mut cfg, preset);
                    cfg.preset_mode = true;
                }
                flow.activate_action("win.next-step", None).ok();
            }
        });
    }

    let builtin_clamp = adw::Clamp::builder()
        .maximum_size(1200)
        .child(&builtin_flow)
        .build();
    builtin_group.add(&builtin_clamp);
    content.append(&builtin_group);

    // Wire custom operation toggles to job config
    {
        let jc = state.job_config.clone();
        resize_check.connect_active_notify(move |row| {
            jc.borrow_mut().resize_enabled = row.is_active();
        });
    }
    {
        let jc = state.job_config.clone();
        adjustments_check.connect_active_notify(move |row| {
            jc.borrow_mut().adjustments_enabled = row.is_active();
        });
    }
    {
        let jc = state.job_config.clone();
        convert_check.connect_active_notify(move |row| {
            jc.borrow_mut().convert_enabled = row.is_active();
        });
    }
    {
        let jc = state.job_config.clone();
        compress_check.connect_active_notify(move |row| {
            jc.borrow_mut().compress_enabled = row.is_active();
        });
    }
    {
        let jc = state.job_config.clone();
        metadata_check.connect_active_notify(move |row| {
            jc.borrow_mut().metadata_enabled = row.is_active();
        });
    }
    {
        let jc = state.job_config.clone();
        watermark_check.connect_active_notify(move |row| {
            jc.borrow_mut().watermark_enabled = row.is_active();
        });
    }
    {
        let jc = state.job_config.clone();
        rename_check.connect_active_notify(move |row| {
            jc.borrow_mut().rename_enabled = row.is_active();
        });
    }

    // User presets section
    let user_group = adw::PreferencesGroup::builder()
        .title("Your Presets")
        .description("Import or save your own workflows")
        .build();

    // FlowBox for user preset cards (same look as built-in presets)
    let user_flow = gtk::FlowBox::builder()
        .selection_mode(gtk::SelectionMode::Single)
        .max_children_per_line(5)
        .min_children_per_line(2)
        .row_spacing(8)
        .column_spacing(8)
        .homogeneous(true)
        .build();
    user_flow.update_property(&[
        gtk::accessible::Property::Label("Your saved preset selection grid"),
    ]);

    let user_clamp = adw::Clamp::builder()
        .maximum_size(1200)
        .child(&user_flow)
        .build();

    let user_empty_label = gtk::Label::builder()
        .label("No saved presets yet. Process images and save your workflow as a preset, or import one.")
        .css_classes(["dim-label"])
        .halign(gtk::Align::Center)
        .wrap(true)
        .justify(gtk::Justification::Center)
        .margin_top(8)
        .margin_bottom(8)
        .build();

    user_group.add(&user_clamp);
    user_group.add(&user_empty_label);

    content.append(&user_group);
    content.append(&custom_group);

    scrolled.set_child(Some(&content));

    // Drop target for .pixstrip-preset files
    let drop_target = gtk::DropTarget::new(gtk::gio::File::static_type(), gtk::gdk::DragAction::COPY);
    let jc_drop = state.job_config.clone();
    drop_target.connect_drop(move |_target, value, _x, _y| {
        if let Ok(file) = value.get::<gtk::gio::File>() {
            if let Some(path) = file.path() {
                if path.extension().and_then(|e| e.to_str()) == Some("pixstrip-preset") {
                    let store = pixstrip_core::storage::PresetStore::new();
                    if let Ok(preset) = store.import_from_file(&path) {
                        apply_preset_to_config(&mut jc_drop.borrow_mut(), &preset);
                        let _ = store.save(&preset);
                        return true;
                    }
                }
            }
        }
        false
    });
    scrolled.add_controller(drop_target);

    let page = adw::NavigationPage::builder()
        .title("Choose a Workflow")
        .tag("step-workflow")
        .child(&scrolled)
        .build();

    // Refresh user presets every time this page is shown
    {
        let uf = user_flow.clone();
        let uel = user_empty_label.clone();
        page.connect_map(move |_| {
            // Clear existing cards
            uf.remove_all();

            let store = pixstrip_core::storage::PresetStore::new();
            let mut has_custom = false;
            if let Ok(presets) = store.list() {
                for preset in &presets {
                    if !preset.is_custom {
                        continue;
                    }
                    has_custom = true;

                    let overlay = gtk::Overlay::new();

                    // Card body (same style as built-in presets)
                    let card = gtk::Box::builder()
                        .orientation(gtk::Orientation::Vertical)
                        .spacing(8)
                        .hexpand(true)
                        .vexpand(false)
                        .build();
                    card.add_css_class("card");
                    card.set_size_request(180, 140);
                    card.update_property(&[
                        gtk::accessible::Property::Label(&format!("{}: {}", preset.name, preset.description)),
                    ]);

                    let inner = gtk::Box::builder()
                        .orientation(gtk::Orientation::Vertical)
                        .spacing(4)
                        .margin_top(12)
                        .margin_bottom(12)
                        .margin_start(12)
                        .margin_end(12)
                        .halign(gtk::Align::Center)
                        .valign(gtk::Align::Center)
                        .vexpand(true)
                        .build();

                    let icon = gtk::Image::builder()
                        .icon_name(&preset.icon)
                        .pixel_size(32)
                        .build();
                    icon.set_accessible_role(gtk::AccessibleRole::Presentation);
                    if !preset.icon_color.is_empty() {
                        icon.add_css_class(&preset.icon_color);
                    }

                    let name_label = gtk::Label::builder()
                        .label(&preset.name)
                        .css_classes(["heading"])
                        .ellipsize(gtk::pango::EllipsizeMode::End)
                        .max_width_chars(16)
                        .build();

                    let desc_label = gtk::Label::builder()
                        .label(&preset.description)
                        .css_classes(["caption", "dim-label"])
                        .wrap(true)
                        .justify(gtk::Justification::Center)
                        .max_width_chars(20)
                        .build();

                    inner.append(&icon);
                    inner.append(&name_label);
                    inner.append(&desc_label);
                    card.append(&inner);
                    overlay.set_child(Some(&card));

                    // Action buttons overlay (top-right corner)
                    let actions_box = gtk::Box::builder()
                        .orientation(gtk::Orientation::Horizontal)
                        .spacing(0)
                        .halign(gtk::Align::End)
                        .valign(gtk::Align::Start)
                        .margin_top(2)
                        .margin_end(2)
                        .build();

                    let export_btn = gtk::Button::builder()
                        .icon_name("document-save-as-symbolic")
                        .tooltip_text("Export preset")
                        .build();
                    export_btn.add_css_class("flat");
                    export_btn.add_css_class("circular");
                    let preset_for_export = preset.clone();
                    export_btn.connect_clicked(move |btn| {
                        let p = preset_for_export.clone();
                        let dialog = gtk::FileDialog::builder()
                            .title("Export Preset")
                            .initial_name(&format!("{}.pixstrip-preset", p.name))
                            .modal(true)
                            .build();
                        if let Some(window) = btn.root().and_then(|r| r.downcast::<gtk::Window>().ok()) {
                            dialog.save(Some(&window), gtk::gio::Cancellable::NONE, move |result| {
                                if let Ok(file) = result
                                    && let Some(path) = file.path()
                                {
                                    let store = pixstrip_core::storage::PresetStore::new();
                                    let _ = store.export_to_file(&p, &path);
                                }
                            });
                        }
                    });

                    let delete_btn = gtk::Button::builder()
                        .icon_name("user-trash-symbolic")
                        .tooltip_text("Delete preset")
                        .build();
                    delete_btn.add_css_class("flat");
                    delete_btn.add_css_class("circular");
                    delete_btn.add_css_class("error");
                    let pname = preset.name.clone();
                    let uf_ref = uf.clone();
                    let uel_ref = uel.clone();
                    delete_btn.connect_clicked(move |btn| {
                        let store = pixstrip_core::storage::PresetStore::new();
                        let _ = store.delete(&pname);
                        // Remove the FlowBoxChild containing this card
                        if let Some(child) = btn.ancestor(gtk::FlowBoxChild::static_type()) {
                            if let Some(fbc) = child.downcast_ref::<gtk::FlowBoxChild>() {
                                uf_ref.remove(fbc);
                                // Show empty label if only the import card is left
                                let mut c = uf_ref.first_child();
                                let mut count = 0;
                                while let Some(w) = c {
                                    count += 1;
                                    c = w.next_sibling();
                                }
                                uel_ref.set_visible(count <= 1);
                            }
                        }
                    });

                    actions_box.append(&export_btn);
                    actions_box.append(&delete_btn);
                    overlay.add_overlay(&actions_box);

                    uf.append(&overlay);
                }
            }
            uel.set_visible(!has_custom);

            // Always append an "Import Preset" card at the end
            let import_card = build_import_card();
            uf.append(&import_card);
        });
    }

    // Wire user preset card activation
    {
        let jc = state.job_config.clone();
        user_flow.connect_child_activated(move |flow, child| {
            // Count total children to know which is the import card (always last)
            let mut total = 0usize;
            let mut c = flow.first_child();
            while let Some(w) = c {
                total += 1;
                c = w.next_sibling();
            }

            let activated_idx = child.index() as usize;

            // Last card is always the import card
            if activated_idx == total - 1 {
                flow.activate_action("win.import-preset", None).ok();
                return;
            }

            let store = pixstrip_core::storage::PresetStore::new();
            if let Ok(presets) = store.list() {
                let custom_presets: Vec<_> = presets.iter().filter(|p| p.is_custom).collect();
                if let Some(preset) = custom_presets.get(activated_idx) {
                    let mut cfg = jc.borrow_mut();
                    apply_preset_to_config(&mut cfg, preset);
                    cfg.preset_mode = true;
                    drop(cfg);
                    flow.activate_action("win.next-step", None).ok();
                }
            }
        });
    }

    page
}

fn apply_preset_to_config(cfg: &mut JobConfig, preset: &Preset) {
    // Resize
    match &preset.resize {
        Some(ResizeConfig::ByWidth(w)) => {
            cfg.resize_enabled = true;
            cfg.resize_width = *w;
            cfg.resize_height = 0;
            cfg.allow_upscale = false;
        }
        Some(ResizeConfig::ByHeight(h)) => {
            cfg.resize_enabled = true;
            cfg.resize_width = 0;
            cfg.resize_height = *h;
            cfg.allow_upscale = false;
        }
        Some(ResizeConfig::FitInBox { max, allow_upscale }) => {
            cfg.resize_enabled = true;
            cfg.resize_width = max.width;
            cfg.resize_height = max.height;
            cfg.allow_upscale = *allow_upscale;
        }
        Some(ResizeConfig::Exact(dims)) => {
            cfg.resize_enabled = true;
            cfg.resize_width = dims.width;
            cfg.resize_height = dims.height;
            cfg.allow_upscale = true;
        }
        None => {
            cfg.resize_enabled = false;
        }
    }

    // Convert
    match &preset.convert {
        Some(ConvertConfig::SingleFormat(fmt)) => {
            cfg.convert_enabled = true;
            cfg.convert_format = Some(*fmt);
        }
        Some(_) => {
            cfg.convert_enabled = true;
            cfg.convert_format = None;
        }
        None => {
            cfg.convert_enabled = false;
            cfg.convert_format = None;
        }
    }

    // Compress
    match &preset.compress {
        Some(CompressConfig::Preset(q)) => {
            cfg.compress_enabled = true;
            cfg.quality_preset = *q;
        }
        Some(CompressConfig::Custom { jpeg_quality, png_level, webp_quality, .. }) => {
            cfg.compress_enabled = true;
            if let Some(jq) = jpeg_quality {
                cfg.jpeg_quality = *jq;
            }
            if let Some(pl) = png_level {
                cfg.png_level = *pl;
            }
            if let Some(wq) = webp_quality {
                cfg.webp_quality = *wq as u8;
            }
        }
        None => {
            cfg.compress_enabled = false;
        }
    }

    // Metadata
    match &preset.metadata {
        Some(MetadataConfig::StripAll) => {
            cfg.metadata_enabled = true;
            cfg.metadata_mode = MetadataMode::StripAll;
        }
        Some(MetadataConfig::Privacy) => {
            cfg.metadata_enabled = true;
            cfg.metadata_mode = MetadataMode::Privacy;
        }
        Some(MetadataConfig::KeepAll) => {
            cfg.metadata_enabled = true;
            cfg.metadata_mode = MetadataMode::KeepAll;
        }
        Some(MetadataConfig::Custom { strip_gps, strip_camera, strip_software, strip_timestamps, strip_copyright }) => {
            cfg.metadata_enabled = true;
            cfg.metadata_mode = MetadataMode::Custom;
            cfg.strip_gps = *strip_gps;
            cfg.strip_camera = *strip_camera;
            cfg.strip_software = *strip_software;
            cfg.strip_timestamps = *strip_timestamps;
            cfg.strip_copyright = *strip_copyright;
        }
        None => {
            cfg.metadata_enabled = false;
        }
    }
}

fn build_custom_card() -> gtk::Box {
    let card = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .spacing(8)
        .hexpand(true)
        .vexpand(false)
        .build();
    card.add_css_class("card");
    card.set_size_request(180, 140);
    card.update_property(&[
        gtk::accessible::Property::Label("Custom: Pick and choose operations"),
    ]);

    let inner = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .spacing(4)
        .margin_top(12)
        .margin_bottom(12)
        .margin_start(12)
        .margin_end(12)
        .halign(gtk::Align::Center)
        .valign(gtk::Align::Center)
        .vexpand(true)
        .build();

    let icon = gtk::Image::builder()
        .icon_name("emblem-system-symbolic")
        .pixel_size(32)
        .build();
    icon.set_accessible_role(gtk::AccessibleRole::Presentation);

    let name_label = gtk::Label::builder()
        .label("Custom")
        .css_classes(["heading"])
        .build();

    let desc_label = gtk::Label::builder()
        .label("Pick and choose operations")
        .css_classes(["caption", "dim-label"])
        .wrap(true)
        .justify(gtk::Justification::Center)
        .max_width_chars(20)
        .build();

    inner.append(&icon);
    inner.append(&name_label);
    inner.append(&desc_label);
    card.append(&inner);

    card
}

fn build_import_card() -> gtk::Box {
    let card = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .spacing(8)
        .hexpand(true)
        .vexpand(false)
        .build();
    card.add_css_class("card");
    card.set_size_request(180, 140);
    card.set_tooltip_text(Some("Import a .pixstrip-preset file from disk"));
    card.update_property(&[
        gtk::accessible::Property::Label("Import preset from file"),
    ]);

    let inner = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .spacing(4)
        .margin_top(12)
        .margin_bottom(12)
        .margin_start(12)
        .margin_end(12)
        .halign(gtk::Align::Center)
        .valign(gtk::Align::Center)
        .vexpand(true)
        .build();

    let icon = gtk::Image::builder()
        .icon_name("folder-open-symbolic")
        .pixel_size(32)
        .build();
    icon.set_accessible_role(gtk::AccessibleRole::Presentation);

    let name_label = gtk::Label::builder()
        .label("Import Preset")
        .css_classes(["heading"])
        .build();

    let desc_label = gtk::Label::builder()
        .label("Load a preset from file")
        .css_classes(["caption", "dim-label"])
        .wrap(true)
        .justify(gtk::Justification::Center)
        .max_width_chars(20)
        .build();

    inner.append(&icon);
    inner.append(&name_label);
    inner.append(&desc_label);
    card.append(&inner);

    card
}

fn build_preset_card(preset: &Preset) -> gtk::Box {
    let card = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .spacing(8)
        .hexpand(true)
        .vexpand(false)
        .build();
    card.add_css_class("card");
    card.set_size_request(180, 140);
    card.update_property(&[
        gtk::accessible::Property::Label(&format!("{}: {}", preset.name, preset.description)),
    ]);

    let inner = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .spacing(4)
        .margin_top(12)
        .margin_bottom(12)
        .margin_start(12)
        .margin_end(12)
        .halign(gtk::Align::Center)
        .valign(gtk::Align::Center)
        .vexpand(true)
        .build();

    let icon = gtk::Image::builder()
        .icon_name(&preset.icon)
        .pixel_size(32)
        .build();
    icon.set_accessible_role(gtk::AccessibleRole::Presentation);
    if !preset.icon_color.is_empty() {
        icon.add_css_class(&preset.icon_color);
    }

    let name_label = gtk::Label::builder()
        .label(&preset.name)
        .css_classes(["heading"])
        .build();

    let desc_label = gtk::Label::builder()
        .label(&preset.description)
        .css_classes(["caption", "dim-label"])
        .wrap(true)
        .justify(gtk::Justification::Center)
        .max_width_chars(20)
        .build();

    inner.append(&icon);
    inner.append(&name_label);
    inner.append(&desc_label);
    card.append(&inner);

    card
}
