namespace QuickSetup {
    const string INSTALLED_ICON_PATH = "/usr/share/quick-setup/icons/";
    const string DEV_ICON_PATH = "data/icons/";

    public class AppData : Object {
        public string name;
        public string app_id;
        public string description;
        public string styleclass;
        public string package_manager = "flathub";
        public bool recommended = false;
        public bool checked { get; set; default = false; }
        public string? sub_category;
    }

    public class CategoryData: Object {
        public string name;
        public string description;
        public string icon_name;
        public bool allow_success_styleclass = false;
        public List<SubCategoryData> sub_categories;
        public List<AppData> apps;
        public List<AppData> selected_apps;
    }

    public class SubCategoryData: Object {
        public string id;
        public string name;
        public string description;
    }

    public class SubCategoryGroup : Object {
        public string id;
        public Adw.PreferencesGroup group;
        
        public SubCategoryGroup(string id, Adw.PreferencesGroup group) {
            this.id = id;
            this.group = group;
        }
    }

    public class CategoryPage: QsPage {
        protected Adw.PreferencesPage selection_page;
        private List<SubCategoryGroup> subcategory_groups;
        private Adw.PreferencesGroup uncategorized_group;
        
        protected CategoryData category;
        public override string page_id { get { return "appcategory"; } }
        public override bool can_go_back_to { get { return false; } }

        public CategoryPage(PageContext context, CategoryData category) {
            base(context, category.name);
            
            this.category = category;
            this.subcategory_groups = new List<SubCategoryGroup>();
            
            this.setup_ui();
            this.populate_apps();
        }

        private void setup_ui() {
            // Create the main preferences page
            this.selection_page = new Adw.PreferencesPage();
            this.selection_page.title = this.category.name;
            this.selection_page.icon_name = this.category.icon_name;
            this.selection_page.vexpand = true;
            this.selection_page.hexpand = true;
            this.selection_page.valign = Gtk.Align.CENTER;
            this.selection_page.halign = Gtk.Align.FILL;
            
            // Create preference groups for each subcategory
            foreach (var sub_category in this.category.sub_categories) {
                var group = new Adw.PreferencesGroup();
                group.title = sub_category.name;
                group.description = sub_category.description;
                
                var sub_group = new SubCategoryGroup(sub_category.id, group);
                this.subcategory_groups.append(sub_group);
                this.selection_page.add(group);
            }
            
            // Create an uncategorized group for apps without subcategories.
            this.uncategorized_group = new Adw.PreferencesGroup();
            this.selection_page.add(this.uncategorized_group);
            
            this.add_content(this.selection_page);
        }

        protected void populate_apps() {
            foreach (var app in this.category.apps) {
                this.add_app_row(app);
            }
        }

        private Adw.PreferencesGroup? find_subcategory_group(string? subcategory_id) {
            if (subcategory_id == null) {
                return null;
            }
            
            foreach (var sub_group in this.subcategory_groups) {
                if (sub_group.id == subcategory_id) {
                    return sub_group.group;
                }
            }
            return null;
        }

        private void add_app_row(AppData app) {
            var app_row = new Adw.ActionRow();
            app_row.title = app.name;
            app_row.subtitle = app.description;
            
            // Add icon if available - check installed path first, then dev path
            var icon = new Gtk.Image.from_icon_name("application-x-executable");
            var icon_path = INSTALLED_ICON_PATH + app.name + ".png";
            if (!File.new_for_path(icon_path).query_exists()) {
                icon_path = DEV_ICON_PATH + app.name + ".png";
            }
            if (!File.new_for_path(icon_path).query_exists() && app.name.has_suffix(" (Web)")) {
                string base_name = app.name.substring(0, app.name.length - " (Web)".length);
                icon_path = INSTALLED_ICON_PATH + base_name + ".png";
                if (!File.new_for_path(icon_path).query_exists()) {
                    icon_path = DEV_ICON_PATH + base_name + ".png";
                }
            }
            if (File.new_for_path(icon_path).query_exists()) {
                icon = new Gtk.Image.from_file(icon_path);
            }

            icon.add_css_class("icon-dropshadow");
            icon.pixel_size = 24;
            app_row.add_prefix(icon);
            
            // Check if app is installable (has non-empty app_id)
            bool is_installable = app.app_id != null && app.app_id.strip() != "";
            
            if (is_installable) {
                // Add checkbox for installable apps
                var checkbox = new Gtk.CheckButton();
                checkbox.active = app.checked;
                checkbox.notify["active"].connect(() => {
                    app.checked = checkbox.active;
                    this.on_app_selection_changed(app);
                });
                app_row.add_suffix(checkbox);
                app_row.set_activatable_widget(checkbox);
            } else {
                // Add status label for non-installable apps
                var status_label = new Gtk.Label("");
                
                // Determine status based on description or add a specific field
                if (app.description.down().contains("preinstalled") || app.description.down().contains("pre-installed")) {
                    status_label.set_text(tr("Preinstalled"));
                    status_label.add_css_class("success");
                } else if (app.description.down().contains("coming soon") || app.description.down().contains("soon")) {
                    status_label.set_text(tr("Coming Soon"));
                    status_label.add_css_class("warning");
                } else {
                    status_label.set_text(tr("Not Available"));
                    status_label.add_css_class("dim-label");
                }
                
                status_label.valign = Gtk.Align.CENTER;
                app_row.add_suffix(status_label);
                
                // Make the row non-activatable for non-installable apps
                app_row.set_activatable(false);
                app_row.add_css_class("dim-label");
            }
            
            // Apply style class if specified
            if (app.styleclass != null && app.styleclass != "") {
                if (app.styleclass != "success" || this.should_show_success_styleclass(app)) {
                    app_row.add_css_class(app.styleclass);
                }
            }
            
            // Add to appropriate group
            var target_group = this.find_subcategory_group(app.sub_category);
            if (target_group != null) {
                target_group.add(app_row);
            } else {
                this.uncategorized_group.add(app_row);
            }
        }

        protected virtual void on_app_selection_changed(AppData app) {
            // This method can be overridden by subclasses to handle app selection
            // Only add installable apps to the selected list
            bool is_installable = app.app_id != null && app.app_id.strip() != "";
            if (!is_installable) {
                return;
            }
            
            // Update the selected_apps list
            if (app.checked) {
                if (this.category.selected_apps.find(app) == null) {
                    this.category.selected_apps.append(app);
                }
            } else {
                this.category.selected_apps.remove(app);
            }
        }

        public unowned List<AppData> get_selected_apps() {
            return this.category.selected_apps;
        }

        public void set_app_checked(string app_id, bool checked) {
            foreach (var app in this.category.apps) {
                if (app.app_id == app_id) {
                    app.checked = checked;
                    break;
                }
            }
        }

        protected virtual bool should_show_success_styleclass(AppData app) {
            if (this.category.allow_success_styleclass) {
                return true;
            }

            if (app.recommended) {
                return true;
            }

            if (app.description == null) {
                return false;
            }

            var description = app.description.down();
            return description.contains("preinstalled") || description.contains("pre-installed");
        }
    }
}
