use gtk::prelude::*;
use gtk::accessible::Property as AccessibleProperty;

use crate::core::database::AppImageRecord;
use crate::core::wayland::WaylandStatus;
use super::widgets;

/// Build a grid card for an AppImage.
pub fn build_app_card(record: &AppImageRecord) -> gtk::FlowBoxChild {
    let card = gtk::Box::builder()
        .orientation(gtk::Orientation::Vertical)
        .spacing(6)
        .halign(gtk::Align::Fill)
        .build();
    card.add_css_class("card");

    let name = record.app_name.as_deref().unwrap_or(&record.filename);

    // Icon (64x64) with integration emblem overlay
    let icon_widget = widgets::app_icon(
        record.icon_path.as_deref(),
        name,
        64,
    );
    icon_widget.add_css_class("icon-dropshadow");

    let icon_overlay = gtk::Overlay::new();
    icon_overlay.set_child(Some(&icon_widget));

    if record.integrated {
        let emblem = gtk::Image::from_icon_name("emblem-ok-symbolic");
        emblem.set_pixel_size(16);
        emblem.add_css_class("integration-emblem");
        emblem.set_halign(gtk::Align::End);
        emblem.set_valign(gtk::Align::End);
        emblem.update_property(&[AccessibleProperty::Label("Integrated into desktop menu")]);
        icon_overlay.add_overlay(&emblem);
    }

    if record.sandbox_mode.as_deref() == Some("firejail") {
        let shield = gtk::Image::from_icon_name("security-high-symbolic");
        shield.set_pixel_size(16);
        shield.set_halign(gtk::Align::Start);
        shield.set_valign(gtk::Align::End);
        shield.set_tooltip_text(Some("This app runs with security restrictions (Firejail sandbox)"));
        shield.update_property(&[AccessibleProperty::Label("Sandboxed with Firejail")]);
        icon_overlay.add_overlay(&shield);
    }

    card.append(&icon_overlay);

    // App name
    let name_label = gtk::Label::builder()
        .label(name)
        .css_classes(["title-4"])
        .ellipsize(gtk::pango::EllipsizeMode::End)
        .max_width_chars(20)
        .build();
    card.append(&name_label);

    // Version + size combined on one line
    let version_text = record.app_version.as_deref().unwrap_or("");
    let size_text = widgets::format_size(record.size_bytes);
    let meta_text = if version_text.is_empty() {
        size_text
    } else {
        format!("{} - {}", version_text, size_text)
    };
    let meta_label = gtk::Label::builder()
        .label(&meta_text)
        .css_classes(["caption", "dimmed", "numeric"])
        .ellipsize(gtk::pango::EllipsizeMode::End)
        .build();
    card.append(&meta_label);

    // Description snippet (if available)
    if let Some(ref desc) = record.description {
        if !desc.is_empty() {
            let snippet = if desc.len() > 60 {
                format!("{}...", &desc[..desc.char_indices().take_while(|&(i, _)| i < 57).last().map(|(i, c)| i + c.len_utf8()).unwrap_or(57)])
            } else {
                desc.clone()
            };
            let desc_label = gtk::Label::builder()
                .label(&snippet)
                .css_classes(["caption", "dimmed"])
                .ellipsize(gtk::pango::EllipsizeMode::End)
                .lines(2)
                .wrap(true)
                .xalign(0.5)
                .max_width_chars(25)
                .build();
            card.append(&desc_label);
        }
    }

    // Single most important badge (priority: Update > FUSE issue)
    if let Some(badge) = build_priority_badge(record) {
        let badge_box = gtk::Box::builder()
            .orientation(gtk::Orientation::Horizontal)
            .halign(gtk::Align::Center)
            .margin_top(2)
            .build();
        badge_box.append(&badge);
        card.append(&badge_box);
    }

    let child = gtk::FlowBoxChild::builder()
        .child(&card)
        .build();
    child.add_css_class("activatable");
    super::widgets::set_pointer_cursor(&child);

    // Accessible label for screen readers
    let accessible_name = build_accessible_label(record);
    child.update_property(&[AccessibleProperty::Label(&accessible_name)]);

    child
}

/// Return the single most important badge for a record.
/// Priority: Analyzing > Update available > FUSE issue > Portable.
/// Wayland details are left to the detail view.
pub fn build_priority_badge(record: &AppImageRecord) -> Option<gtk::Label> {
    // 0. Analysis in progress
    if record.app_name.is_none() && record.analysis_status.as_deref() != Some("complete") {
        return Some(widgets::status_badge("Analyzing...", "info"));
    }

    // 1. Update available
    if let (Some(ref latest), Some(ref current)) = (&record.latest_version, &record.app_version) {
        if crate::core::updater::version_is_newer(latest, current) {
            return Some(widgets::status_badge("Update", "info"));
        }
    }

    // 2. FUSE issue (cannot launch)
    if let Some(ref fs) = record.fuse_status {
        let is_ok = matches!(
            fs.as_str(),
            "native_fuse" | "static_runtime" | "fully_functional" | "extract_and_run"
        );
        if !is_ok {
            let badge = widgets::status_badge("Needs setup", "warning");
            badge.set_tooltip_text(Some("FUSE (Filesystem in Userspace) is required to run this AppImage"));
            return Some(badge);
        }
    }

    // 3. Portable / removable media
    if record.is_portable {
        let badge = widgets::status_badge("Portable", "info");
        badge.set_tooltip_text(Some("This app is stored on removable media"));
        return Some(badge);
    }

    // 4. Fallback: integration status
    if record.integrated {
        return Some(widgets::status_badge("Ready", "success"));
    }

    Some(widgets::status_badge("Not in menu", "neutral"))
}

/// Build a descriptive accessible label for screen readers.
fn build_accessible_label(record: &AppImageRecord) -> String {
    let name = record.app_name.as_deref().unwrap_or(&record.filename);
    let mut parts = vec![name.to_string()];

    if let Some(ref ver) = record.app_version {
        parts.push(format!("version {}", ver));
    }

    parts.push(widgets::format_size(record.size_bytes));

    if record.integrated {
        parts.push("integrated".to_string());
    }

    if let Some(ref ws) = record.wayland_status {
        let status = WaylandStatus::from_str(ws);
        if status != WaylandStatus::Unknown {
            parts.push(format!("Wayland: {}", status.label()));
        }
    }

    parts.join(", ")
}
